简体   繁体   English

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

[英]Java Interface : Use default method implementation in implementation classes

I have an interface and its 2 or more implementations say,我有一个接口,它的 2 个或更多实现说,

public interface IProcessor {
  default void method1() {
   //logic
  }
  default void method2() {
   //logic
  }
  public void method3();
  public void method4();
}

Here, The method1 and method2 implementation logic is common across all multiple multiple implementation classes.这里, method1method2实现逻辑在所有多个多个实现类中是通用的。 So defined as default methods.所以定义为默认方法。 So only the rest of the methods can be overridden in the implementation classes.所以只有rest的方法可以在实现类中被覆盖。

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
  }
}

Is there a better approach that I can achieve this without default methods and without redundant code in the respective implementation classes ?有没有更好的方法可以在没有默认方法和相应实现类中没有冗余代码的情况下实现这一目标? Because if the code in the default methods increases then the interface looks clumsy.因为如果default方法中的代码增加,那么界面看起来很笨拙。

Default methods can be overridden可以覆盖默认方法

You said:你说:

So only the rest of the methods can be overridden in the implementation classes.所以只有rest的方法可以在实现类中被覆盖。

The word "only" there is incorrect.那里的“唯一”一词是不正确的。 A default method in an interface can indeed be overridden by an implementing class.实现 class 确实可以覆盖接口中的默认方法。 Thus the word default used as the keyword here, meaning: use this method code if no other implementing code is present at runtime.因此这里使用的单词default作为关键字,意思是:如果在运行时没有其他实现代码,则使用此方法代码。

Here is a silly contrived example where we define an interface Fruit with a default method isJuicy that returns true .这是一个愚蠢的人为设计的示例,其中我们定义了一个带有默认方法isJuicy返回true的接口Fruit We have two subclasses, Orange and Banana .我们有两个子类, OrangeBanana The first has no override of isJuicy , so its behavior comes from the default method.第一个没有覆盖isJuicy ,因此它的行为来自默认方法。 The second demonstrates that you can override the default method.第二个演示您可以覆盖默认方法。 Here we see the override return false .在这里,我们看到覆盖返回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;
        }
    }
}

When run.跑的时候。

new Orange().isJuicy(): true
new Banana().isJuicy(): false

Prefer abstract classes over default methods优先使用抽象类而不是默认方法

You asked:您问:

Is there a better approach that I can achieve this without default methods and without redundant code in the respective implementation classes?有没有更好的方法可以在没有默认方法并且在各个实现类中没有冗余代码的情况下实现这一目标?

I do suggest you not use default interface methods for this.我建议您不要为此使用default接口方法。

The idea and technology for adding default methods to Java interfaces was not as a feature in itself, but as a solution to another problem: Retrofitting functionality onto existing interfaces to support new lambda features but without breaking the existing code of millions of Java programmers as would happen when otherwise adding methods to existing interfaces.将默认方法添加到 Java 接口的想法和技术本身并不是一个功能,而是作为另一个问题的解决方案:在现有接口上改造功能以支持新的 lambda 功能,但不会破坏数百万 ZD5238AZ7880E15EA218 程序员的现有代码。否则会在向现有接口添加方法时发生。 By inventing default method on interfaces, the Java team was able to add more methods to existing interfaces while relieving all existing implementations of the need to implement those new methods.通过在接口上发明default方法,Java 团队能够向现有接口添加更多方法,同时减轻所有现有实现对实现这些新方法的需求。 New features, without breaking code, a hallmark of Java.新功能,无需破解代码,是 Java 的标志。

As stated in State of the Lambda by Brian Goetz 2013-09 :Brian Goetz 2013-09的 Lambda 的 State 所述

The purpose of default methods (…) is to enable interfaces to be evolved in a compatible manner after their initial publication.默认方法(...) 的目的是使接口在初始发布后能够以兼容的方式进行演变。

My own opinion is that programmers are generally not going to expect behavior to be built into your interfaces.我自己的观点是,程序员通常不会期望将行为内置到您的接口中。 The classic use of an interface in Java is to define a contract per the method signatures , not define behavior (code). Java 中接口的经典用法是根据 方法签名定义合约,而不是定义行为(代码)。 So consider adding adding behavior (code) as default methods only as a last resort.所以考虑添加添加行为(代码)作为默认方法仅作为最后的手段。

Instead, define your interface as a contract, with no default methods.相反,将您的接口定义为合同,没有默认方法。 At least no default methods at first;至少一开始没有默认方法; you may find later a need as did Brian Goetz and the Java team to add default methods later.您可能会发现以后需要像 Brian Goetz 和 Java 团队一样稍后添加默认方法。 But start with only the contract.但从合同开始。

Then define an abstract class that implements that interface.然后定义一个实现该接口的抽象 class。 Any behavior (code) to be shared across the various subclasses can be moved into this abstract class.任何要在各个子类之间共享的行为(代码)都可以移动到这个抽象的 class 中。

Then go on to define subclasses, concrete classes, that inherit from your abstract class.然后 go 定义继承自抽象 class 的子类,具体类。

With this classic and common approach of interface + abstract class + concrete classes, you have flexibility to make changes, and to make testing easier (with stubs rather than real classes), while efficiently sharing code from one place yet allowing overrides where needed.使用这种经典且通用的接口 + 抽象 class + 具体类的方法,您可以灵活地进行更改,并使测试更容易(使用存根而不是真实类),同时从一个地方有效地共享代码,但允许在需要时进行覆盖。

You don't do anything wrong, although I'd say abstract classes are better suited in this case, when you have method implementations ( method1 , method2 ) shared across multiple implementations.你没有做错任何事,虽然我会说抽象类更适合这种情况,当你有跨多个实现共享的方法实现( method1method2 )时。

If you still want it to be an interface, create a interface and an abstract class extending the interface.如果您仍然希望它是一个接口,请创建一个接口和一个抽象 class 扩展该接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM