我有一个接口和它的两个或多个实现,比如
public interface IProcessor {
default void method1() {
//logic
}
default void method2() {
//logic
}
public void method3();
public void method4();
}
这里,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
}
}
有没有更好的方法可以在没有默认方法和各自实现类中没有冗余代码的情况下实现这一点?因为如果default
方法中的代码增加,则接口看起来很笨拙。
可以重写默认方法
你说:
因此,在实现类中只能重写其余的方法。
单词";仅";存在错误。接口中的默认方法确实可以被实现类重写。因此,这里使用单词default
作为关键字,意思是:如果运行时没有其他实现代码,则使用此方法代码。
这里有一个愚蠢的人为例子,我们用返回true
的默认方法isJuicy
定义了一个接口Fruit
。我们有两个子类,Orange
和Banana
。第一个方法没有覆盖isJuicy
,因此它的行为来自默认方法。第二个演示了可以覆盖默认方法。在这里我们可以看到覆盖返回false
。
package work.basil.example;
public class OverridingDefault
{
public static void main ( String[] args )
{
OverridingDefault app = new OverridingDefault();
app.demo();
}
private void demo ( )
{
System.out.println( "new Orange().isJuicy(): " + new Orange().isJuicy() );
System.out.println( "new Banana().isJuicy(): " + new Banana().isJuicy() );
}
public interface Fruit
{
default boolean isJuicy ( )
{
return true;
}
}
public class Orange implements Fruit
{
}
public class Banana implements Fruit
{
@Override
public boolean isJuicy ( )
{
return false;
}
}
}
运行时。
new Orange().isJuicy(): true
new Banana().isJuicy(): false
与默认方法相比,更喜欢抽象类
你问:
有没有更好的方法可以在没有默认方法和相应实现类中没有冗余代码的情况下实现这一点?
我建议您不要为此使用default
接口方法。
向Java接口添加默认方法的想法和技术本身并不是一个功能,而是另一个问题的解决方案:在现有接口上改装功能以支持新的lambda功能,但不会像向现有接口添加方法那样破坏数百万Java程序员的现有代码。通过在接口上发明default
方法,Java团队能够向现有接口添加更多方法,同时减轻所有现有实现实现这些新方法的需要。新特性,不破坏代码,是Java的标志。
正如Brian Goetz 2013-09在《Lambda的状态》中所述:
默认方法(…(的目的是使接口在首次发布后能够以兼容的方式进行开发。
我自己的观点是,程序员通常不会期望行为被构建到您的接口中。Java中接口的经典用法是根据方法签名定义契约,而不是定义行为(代码(。因此,将添加行为(代码(作为默认方法只是最后的手段。
相反,将您的接口定义为一个契约,没有默认方法。至少一开始没有默认方法;稍后您可能会发现需要添加默认方法,就像BrianGoetz和Java团队一样。但从合同开始。
然后定义一个实现该接口的抽象类。要在各个子类之间共享的任何行为(代码(都可以移动到这个抽象类中。
然后继续定义从抽象类继承的子类,具体类。
有了这种经典而常见的接口+抽象类+具体类的方法,您可以灵活地进行更改,并使测试更容易(使用存根而不是真正的类(,同时有效地从一个地方共享代码,并允许在需要时进行重写。
您没有做错任何事情,尽管我认为抽象类更适合这种情况,当您在多个实现之间共享方法实现(method1
、method2
(时。
如果您仍然希望它是一个接口,请创建一个接口和一个扩展接口的抽象类。