Java 8允许在称为default methods的接口中默认实现方法。

我在什么时候使用那种接口默认方法,而不是抽象类(带有抽象方法)之间感到困惑。

那么什么时候应该使用默认方法的接口,什么时候应该使用抽象类(带有抽象方法)?抽象类在这种情况下仍然有用吗?


当前回答

从业务用例上下文中,接口可用于定义特定的业务规则,其中抽象类将定义启动业务的公共结构。

假设某个企业所有者希望与Amazon和Walmart合作,那么这里定义的接口将是WalmartPartner, AmazonPartner将定义特定的业务规则,抽象类BusinessSetup将获得特定区域的业务设置。

// Interfaces
 
public interface WalmartPartner {
    public static boolean signUpForWalmartBusinessAccount(String BusinessId){
        System.out.println("Setting up Walmart Business Partner");
        return true;
    }
    public default  void  getWalmartDeals(){
        System.out.println("Default walmart deal executed !");
    }
    public abstract void setupShopifyForWalmart();
    public abstract  void setupWalmartProducts();

public interface AmazonPartner {
    public static boolean signUpAsAmazonServicePartner(String BusinessId){
        System.out.println("Setting up Amazon Business Partner");
        return true;
    }
    public default  void  paymentPlatformSetup(){
        System.out.println(" Amazon default payment platform is setup");
    }
    public abstract void setupPrimeMemberDealsByRegion();
    public abstract  void setupPrimeDeals();
}

 // Abstract class 

public abstract class BusinessSetup {
    String businessId ;
    public BusinessSetup(String businessId){
        this.businessId = businessId;
        System.out.println("1. Initial Business setup for BusienssID: "+this.businessId+" is Complete");
    }
    public final boolean getBusinessRegisteredInRegion(String region){
        System.out.println("2. Business got registered in "+region+ "!");
        return true;
    }
    public abstract void setupCustomerPlatform(String customerId);
    public abstract void setupVendorPlatform(String vendorId);

}

// Concrete Class 
public class WalMartPartnerImpl extends BusinessSetup implements WalmartPartner {
    public WalMartPartnerImpl(String businessId) {
        super(businessId);
    }
    @Override
    public void setupCustomerPlatform(String customerId) {
    }

    @Override
    public void setupVendorPlatform(String vendorId) {
    }

    @Override
    public void setupShopifyForWalmart() {
    }

    @Override
    public void setupWalmartProducts() {
    }
    public static void main(String args[]){
        WalMartPartnerImpl walMartPartner = new WalMartPartnerImpl("wal8989");
        walMartPartner.getBusinessRegisteredInRegion("california");
        walMartPartner.getWalmartDeals();
        walMartPartner.setupCustomerPlatform("wal8989");

    }
}

其他回答

什么时候应该使用缺省方法的接口,什么时候应该使用 抽象类被使用?

向后兼容性: 想象一下,你的接口是由数百个类实现的,修改这个接口将迫使所有用户实现新添加的方法,即使它对于实现你的接口的许多其他类来说可能不是必需的。另外,它允许你的接口成为一个功能接口

事实与限制:

1-只能在接口中声明,而不能在类或 抽象类。

2 .必须提供一个主体

它不像接口中使用的其他常规方法那样被认为是抽象的。

本文将对此进行描述。想想forEach of Collections。

List<?> list = …
list.forEach(…);

The forEach isn’t declared by java.util.List nor the java.util.Collection interface yet. One obvious solution would be to just add the new method to the existing interface and provide the implementation where required in the JDK. However, once published, it is impossible to add methods to an interface without breaking the existing implementation. The benefit that default methods bring is that now it’s possible to add a new default method to the interface and it doesn’t break the implementations.

Java Interface中的默认方法将更多地用于提供函数的虚拟实现,从而使该接口的任何实现类不必声明所有抽象方法,即使它们只想处理一个抽象方法。 因此,接口中的默认方法在某种程度上更像是适配器类概念的替代品。

然而,抽象类中的方法应该给出一个有意义的实现,只有在需要覆盖一个通用功能时,任何子类才应该覆盖它。

从业务用例上下文中,接口可用于定义特定的业务规则,其中抽象类将定义启动业务的公共结构。

假设某个企业所有者希望与Amazon和Walmart合作,那么这里定义的接口将是WalmartPartner, AmazonPartner将定义特定的业务规则,抽象类BusinessSetup将获得特定区域的业务设置。

// Interfaces
 
public interface WalmartPartner {
    public static boolean signUpForWalmartBusinessAccount(String BusinessId){
        System.out.println("Setting up Walmart Business Partner");
        return true;
    }
    public default  void  getWalmartDeals(){
        System.out.println("Default walmart deal executed !");
    }
    public abstract void setupShopifyForWalmart();
    public abstract  void setupWalmartProducts();

public interface AmazonPartner {
    public static boolean signUpAsAmazonServicePartner(String BusinessId){
        System.out.println("Setting up Amazon Business Partner");
        return true;
    }
    public default  void  paymentPlatformSetup(){
        System.out.println(" Amazon default payment platform is setup");
    }
    public abstract void setupPrimeMemberDealsByRegion();
    public abstract  void setupPrimeDeals();
}

 // Abstract class 

public abstract class BusinessSetup {
    String businessId ;
    public BusinessSetup(String businessId){
        this.businessId = businessId;
        System.out.println("1. Initial Business setup for BusienssID: "+this.businessId+" is Complete");
    }
    public final boolean getBusinessRegisteredInRegion(String region){
        System.out.println("2. Business got registered in "+region+ "!");
        return true;
    }
    public abstract void setupCustomerPlatform(String customerId);
    public abstract void setupVendorPlatform(String vendorId);

}

// Concrete Class 
public class WalMartPartnerImpl extends BusinessSetup implements WalmartPartner {
    public WalMartPartnerImpl(String businessId) {
        super(businessId);
    }
    @Override
    public void setupCustomerPlatform(String customerId) {
    }

    @Override
    public void setupVendorPlatform(String vendorId) {
    }

    @Override
    public void setupShopifyForWalmart() {
    }

    @Override
    public void setupWalmartProducts() {
    }
    public static void main(String args[]){
        WalMartPartnerImpl walMartPartner = new WalMartPartnerImpl("wal8989");
        walMartPartner.getBusinessRegisteredInRegion("california");
        walMartPartner.getWalmartDeals();
        walMartPartner.setupCustomerPlatform("wal8989");

    }
}

正如在其他回答中提到的,添加实现到接口的能力是为了在Collections框架中提供向后兼容性。我认为,提供向后兼容性可能是向接口添加实现的唯一好的理由。

否则,如果您将实现添加到接口,那么您就违反了最初添加接口的基本规律。Java是一种单一继承语言,不像c++允许多重继承。接口提供了支持多重继承的语言所具有的类型优势,而不会引入多重继承所带来的问题。

更具体地说,Java只允许实现的单一继承,但它允许接口的多重继承。例如,以下是有效的Java代码:

class MyObject extends String implements Runnable, Comparable { ... }

MyObject只继承了一个实现,但它继承了三个契约。

Java传递了实现的多重继承,因为实现的多重继承带来了许多棘手的问题,这些问题超出了本文的讨论范围。添加接口是为了允许合约的多重继承(又名接口),而不存在实现的多重继承问题。

为了支持我的观点,这里引用了Ken Arnold和James Gosling在《Java编程语言》(第4版)一书中的一句话:

Single inheritance precludes some useful and correct designs. The problems of multiple inheritance arise from multiple inheritance of implementation, but in many cases multiple inheritance is used to inherit a number of abstract contracts and perhaps one concrete implementation. Providing a means to inherit an abstract contract without inheriting an implementation allows the typing benefits of multiple inheritance without the problems of multiple implementation inheritance. The inheritance of an abstract contract is termed interface inheritance. The Java programming language supports interface inheritance by allowing you to declare an interface type