Java接口:在实现类中使用默认方法实现

man*_*ani 4 java oop design-patterns

我有一个接口及其 2 个或多个实现,

public interface IProcessor {
  default void method1() {
   //logic
  }
  default void method2() {
   //logic
  }
  public void method3();
  public void method4();
}
Run Code Online (Sandbox Code Playgroud)

这里,method1实现method2逻辑在所有多个多个实现类中是通用的。因此定义为默认方法。因此,只能在实现类中重写其余方法。

public CarImpl implements IProcessor {
  @Override 
  public void method3() {
    //logic
  }
  @Override 
  public void method4() {
    //logic
  }
}

public VanImpl implements IProcessor {
  @Override 
  public void method3() {
    //logic
  }
  @Override 
  public void method4() {
    //logic
  }
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法可以在没有默认方法并且在各自的实现类中没有冗余代码的情况下实现这一点?因为如果方法中的代码default增加,那么界面就会显得很笨拙。

Bas*_*que 5

可以覆盖默认方法

\n

你说:

\n
\n

因此,只能在实现类中重写其余方法。

\n
\n

那里的“仅”这个词是不正确的。接口中的默认方法确实可以被实现类覆盖。因此,该词default在这里用作关键字,意思是:如果运行时不存在其他实现代码,则使用此方法代码。

\n

这是一个愚蠢的示例,其中我们定义了一个带有返回 的Fruit默认方法的接口。我们有两个子类,和。第一个没有重写,因此它的行为来自默认方法。第二个演示您可以覆盖默认方法。这里我们看到覆盖返回isJuicytrueOrangeBananaisJuicyfalse

\n
package work.basil.example;\n\npublic class OverridingDefault\n{\n    public static void main ( String[] args )\n    {\n        OverridingDefault app = new OverridingDefault();\n        app.demo();\n    }\n\n    private void demo ( )\n    {\n        System.out.println( "new Orange().isJuicy(): " + new Orange().isJuicy() );\n        System.out.println( "new Banana().isJuicy(): " + new Banana().isJuicy() );\n    }\n\n    public interface Fruit\n    {\n        default boolean isJuicy ( )\n        {\n            return true;\n        }\n    }\n\n    public class Orange implements Fruit\n    {\n    }\n\n    public class Banana implements Fruit\n    {\n        @Override\n        public boolean isJuicy ( )\n        {\n            return false;\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

运行时。

\n
new Orange().isJuicy(): true\nnew Banana().isJuicy(): false\n
Run Code Online (Sandbox Code Playgroud)\n

优先选择抽象类而不是默认方法

\n

你问:

\n
\n

有没有更好的方法可以在没有默认方法并且在各自的实现类中没有冗余代码的情况下实现这一点?

\n
\n

我确实建议您不要default为此使用接口方法。

\n

向 Java 接口添加默认方法的想法和技术本身并不是一个功能,而是另一个问题的解决方案:对现有接口进行功能改造以支持新的 lambda 功能,但又不会破坏数百万 Java 程序员的现有代码。当向现有接口添加方法时会发生这种情况。通过在接口上发明default方法,Java 团队能够向现有接口添加更多方法,同时减轻所有现有实现实现这些新方法的需要。新功能,无需破坏代码,这是 Java 的标志。

\n

正如Brian Goetz 在 2013 年 9 月发表的《Lambda 状态》中所述:

\n
\n

默认方法(\xe2\x80\xa6)的目的是使接口在首次发布后能够以兼容的方式发展。

\n
\n

我自己的观点是,程序员通常不会期望将行为内置到您的界面中。Java 中接口的经典用法是根据方法签名定义契约,而不是定义行为(代码)。因此,请考虑将添加行为(代码)添加为默认方法,仅作为最后的手段。

\n

相反,将您的接口定义为契约,没有默认方法。至少一开始没有默认方法;您稍后可能会像 Brian Goetz 和 Java 团队一样发现需要添加默认方法。但只从合同开始。

\n

然后定义一个实现该接口的抽象类。任何要在各个子类之间共享的行为(代码)都可以移动到这个抽象类中。

\n

然后继续定义从抽象类继承的子类、具体类。

\n

通过接口+抽象类+具体类这种经典且常见的方法,您可以灵活地进行更改,并使测试变得更容易(使用存根而不是真实的类),同时从一个地方有效地共享代码,同时允许在需要时进行覆盖。

\n