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

以下是我的回答:

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.

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

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

我哪里错了?


当前回答

接口是纯粹抽象的。我们在接口中没有任何实现代码。

抽象类包含方法及其实现。

点击这里观看接口和抽象类教程

其他回答

抽象类不是纯粹的抽象,因为它是具体方法(已实现方法)和未实现方法的集合。 但 接口是纯抽象的,因为只有未实现的方法,没有具体的方法。

为什么是抽象类?

如果用户想为所有对象编写通用功能。 抽象类是未来重新实现的最佳选择,可以在不影响最终用户的情况下增加更多的功能。

为什么接口?

如果用户想要编写不同的功能,那将是对象上的不同功能。 一旦接口发布,如果不需要修改需求,接口是最好的选择。

你很好地总结了使用和实现方面的实际差异,但没有提到意义上的差异。

接口是实现类将具有的行为的描述。实现类确保它将拥有这些可以在其上使用的方法。它基本上是类必须做出的契约或承诺。

抽象类是不同子类的基础,这些子类共享不需要重复创建的行为。子类必须完成行为,并有覆盖预定义行为的选项(只要它没有被定义为final或private)。

你会在java中找到很好的例子。util包,它包含了List这样的接口和AbstractList这样已经实现了接口的抽象类。官方文档对AbstractList的描述如下:

该类提供了List接口的框架实现,以最大限度地减少实现该接口所需的工作,该接口由“随机访问”数据存储(例如数组)支持。

接口是一个“契约”,其中实现契约的类承诺实现方法。举个例子,当我将一款游戏从2D升级到3D时,我不得不编写一个界面而不是类。我必须创建一个界面来共享2D和3D版本的游戏类别。

package adventure;
import java.awt.*;
public interface Playable {
    public void playSound(String s);
    public Image loadPicture(String s);    
}

然后我可以实现基于环境的方法,同时仍然能够从一个不知道正在加载的游戏版本的对象调用这些方法。

公共类Adventure扩展了JFrame实现了Playable

公共类Dungeon3D扩展了SimpleApplication实现的Playable

公共类Main扩展了SimpleApplication实现了AnimEventListener ActionListener,播放

通常,在游戏世界中,世界可以是一个抽象类,在游戏中执行方法:

public abstract class World...

    public Playable owner;

    public Playable getOwner() {
        return owner;
    }

    public void setOwner(Playable owner) {
        this.owner = owner;
    }

接口与抽象类的基本区别在于,接口支持多重继承,而抽象类不支持。

在抽象类中,你也可以提供所有的抽象方法,比如接口。

为什么需要抽象类?

在某些情况下,当处理用户请求时,抽象类并不知道用户的意图。在该场景中,我们将在类中定义一个抽象方法,并询问用户谁扩展了这个类,请在抽象方法中提供您的意图。在这种情况下,抽象类非常有用

为什么需要接口?

比如说,我有一份工作,但我在这方面没有经验。的例子, 如果你想建造一座建筑或大坝,那么在这种情况下你会怎么做?

你将确定你的需求是什么,并根据这些需求制定一份合同。 然后打电话给投标者来构建你的项目 无论谁建造这个项目,都应该满足你的要求。但是不同厂商的构造逻辑是不同的。

这里我不关心它们是如何构造的。最终的目标是否满足我的要求,这只是我的关键点。

在这里,你的需求称为接口,构造函数称为实现者。

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

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

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

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