在我的一次采访中,我被要求解释接口类和抽象类之间的区别。

以下是我的回答:

Methods of a Java interface are implicitly abstract and cannot have implementations. A Java abstract class can have instance methods that implements a default behaviour. Variables declared in a Java interface are by default final. An abstract class may contain non-final variables. Members of a Java interface are public by default. A Java abstract class can have the usual flavours of class members like private, protected, etc. A Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”. An interface can extend another Java interface only, an abstract class can extend another Java class and implement multiple Java interfaces. A Java class can implement multiple interfaces but it can extend only one abstract class.

然而,面试官并不满意,他告诉我这种描述代表了“书本知识”。

他让我给出一个更实际的回答,用实际的例子解释我什么时候会选择抽象类而不是接口。

我哪里错了?


当前回答

这个世界上没有什么是完美的。他们可能期待的是更实际的方法。

但在你解释之后,你可以用稍微不同的方法添加这些行。

Interfaces are rules (rules because you must give an implementation to them that you can't ignore or avoid, so that they are imposed like rules) which works as a common understanding document among various teams in software development. Interfaces give the idea what is to be done but not how it will be done. So implementation completely depends on developer by following the given rules (means given signature of methods). Abstract classes may contain abstract declarations, concrete implementations, or both. Abstract declarations are like rules to be followed and concrete implementations are like guidelines (you can use it as it is or you can ignore it by overriding and giving your own implementation to it). Moreover which methods with same signature may change the behaviour in different context are provided as interface declarations as rules to implement accordingly in different contexts.

编辑:Java 8简化了在接口中定义默认方法和静态方法。

public interface SomeInterfaceOne {

    void usualAbstractMethod(String inputString);

    default void defaultMethod(String inputString){
        System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
    }
}

现在,当一个类将实现SomeInterface时,并不强制为interface的默认方法提供实现。

如果我们有另一个具有以下方法的接口:

public interface SomeInterfaceTwo {

    void usualAbstractMethod(String inputString);

    default void defaultMethod(String inputString){
        System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
    }

}

Java不允许扩展多个类,因为这会导致“钻石问题”,即编译器无法决定使用哪个超类方法。如果使用默认方法,接口也会出现菱形问题。因为如果一个类同时实现这两个

SomeInterfaceOne and SomeInterfaceTwo

并且没有实现常见的默认方法,编译器不能决定选择哪一个。 为了避免这个问题,在java 8中必须实现不同接口的通用缺省方法。如果任何类实现了上述两个接口,它必须提供defaultMethod()方法的实现,否则编译器将抛出编译时错误。

其他回答

我先给大家举个例子:

public interface LoginAuth{
   public String encryptPassword(String pass);
   public void checkDBforUser();
}

假设您的应用程序中有3个数据库。然后,该数据库的每个实现都需要定义上述2个方法:

public class DBMySQL implements LoginAuth{
          // Needs to implement both methods
}
public class DBOracle implements LoginAuth{
          // Needs to implement both methods
}
public class DBAbc implements LoginAuth{
          // Needs to implement both methods
}

但是,如果encryptPassword()不依赖于数据库,并且对每个类都是相同的呢?那么上面的方法就不是一个好的方法。

相反,考虑以下方法:

public abstract class LoginAuth{
   public String encryptPassword(String pass){
            // Implement the same default behavior here 
            // that is shared by all subclasses.
   }

   // Each subclass needs to provide their own implementation of this only:
   public abstract void checkDBforUser();
}

现在,在每个子类中,我们只需要实现一个方法——依赖于数据库的方法。

你的回答是对的,但是面试官需要你从软件工程的角度来区分,而不是根据Java的细节。

简单的单词:

An Interface is like the interface of a shop anything that is shown on it should be there in the shop, so any method in the Interface must be there implemented in the concrete class. Now what if some classes share some exact methods and varies in others. Suppose the Interface is about a shop that contains two things and suppose we have two shops both contain sport equipment but one has clothes extra and the other has shoes extra. So what you do is making an abstract class for Sport that implements the Sports method and leave the other method unimplemented. Abstract class here means that this shop doesn't exist itself but it is the base for other classes/shops. This way you are organising the code, avoiding errors of replicating the code, unifying the code, and ensuring re-usability by some other class.

根据我的理解和我的做法,

接口就像一个规范/契约,任何实现接口类的类都必须实现抽象类中定义的所有方法(除了默认方法(在Java 8中引入))

然而,当我知道类的一些方法需要实现时,我定义了一个类抽象,而有些方法我仍然不知道实现是什么(我们可能知道函数签名,但不知道实现)。我这样做是为了在开发的后期,当我知道如何实现这些方法时,我可以扩展这个抽象类并实现这些方法。

注意:接口方法中不能有函数体,除非该方法是静态的或默认的。

这里似乎已经涵盖了几乎所有的东西。在抽象类的实际实现上再补充一点:

Abstract关键字也用于防止类被实例化。如果你有一个具体的类,你不想被实例化-让它抽象。

我相信面试官想要了解的可能是界面和实现之间的区别。

代码模块的接口——不是Java接口,更通用的说法是“接口”——基本上是与使用该接口的客户端代码之间的契约。

代码模块的实现是使模块工作的内部代码。通常,您可以以多种不同的方式实现特定的接口,甚至可以在客户机代码不知道更改的情况下更改实现。

A Java interface should only be used as an interface in the above generic sense, to define how the class behaves for the benefit of client code using the class, without specifying any implementation. Thus, an interface includes method signatures - the names, return types, and argument lists - for methods expected to be called by client code, and in principle should have plenty of Javadoc for each method describing what that method does. The most compelling reason for using an interface is if you plan to have multiple different implementations of the interface, perhaps selecting an implementation depending on deployment configuration.

A Java abstract class, in contrast, provides a partial implementation of the class, rather than having a primary purpose of specifying an interface. It should be used when multiple classes share code, but when the subclasses are also expected to provide part of the implementation. This permits the shared code to appear in only one place - the abstract class - while making it clear that parts of the implementation are not present in the abstract class and are expected to be provided by subclasses.