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

以下是我的回答:

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.

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

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

我哪里错了?


当前回答

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

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

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

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

其他回答

嗯,现在人们渴望实用的方法,你说得很对,但大多数面试官看起来是按照他们目前的要求,想要一个实用的方法。

回答完你的问题后,你应该跳到例子上:

文摘:

例如,我们有一个工资函数,它有一些对所有员工共同的参数。然后我们可以有一个叫做CTC的抽象类,它带有部分定义的方法体,它将被所有类型的员工扩展,并根据他们的额外工资得到补偿。 对于公共功能。

public abstract class CTC {

    public int salary(int hra, int da, int extra)
    {
        int total;
        total = hra+da+extra;
        //incentive for specific performing employee
        //total = hra+da+extra+incentive;
        return total;
    }
}

class Manger extends CTC
{
}


class CEO extends CTC
{
}

class Developer extends CTC
{   
}

接口

Java中的接口允许在不扩展接口功能的情况下拥有接口功能,你必须清楚你想在应用程序中引入的功能签名的实现。它会迫使你做出定义。 不同的功能。

public interface EmployeType {

    public String typeOfEmployee();
}

class ContarctOne implements EmployeType
{

    @Override
    public String typeOfEmployee() {
        return "contract";
    }

}

class PermanentOne implements EmployeType
{

    @Override
    public String typeOfEmployee() {
        return "permanent";
    }

}

通过将methgos定义为抽象类,你也可以对抽象类进行这样的强制活动,现在一个扩展抽象类的类仍然是抽象类,直到它覆盖抽象函数。

为了让你能在面试中给出一个简单、合理的回答,我提供以下几点:

接口用于为一系列相关类指定API——关系就是接口。通常用于具有多个实现的情况,通过配置或在运行时选择正确的实现。(除非使用Spring,此时接口基本上就是Spring Bean)。接口通常用于解决多重继承问题。

抽象类是专门为继承而设计的类。这也意味着有多个实现,所有实现都有一些共性(在抽象类中可以找到)。

如果你想解决这个问题,那么就说抽象类经常实现接口的一部分——job就是你的了!

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

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

为什么需要抽象类?

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

为什么需要接口?

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

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

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

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

我将尝试用实际场景来回答,以说明两者之间的区别。

接口是零负载的,即不需要维护状态,因此将契约(能力)与类关联是更好的选择。

例如,说我有一个执行一些操作的任务类,现在在单独的线程中执行一个任务,我不需要扩展线程类,更好的选择是使任务实现可运行的接口(即实现其run()方法),然后将此任务类的对象传递给线程实例并调用其start()方法。

现在你可以问,如果Runnable是一个抽象类呢?

从技术上讲,这是可能的,但从设计角度来看,这是一个糟糕的选择原因:

Runnable没有与之相关的状态,也没有“提供”任何状态 run()方法的默认实现 Task必须扩展它,因此它不能扩展任何其他类 Task没有提供任何专门化到Runnable类,它所需要的只是重写run()方法

换句话说,Task类需要在线程中运行的能力,这是通过实现Runnable接口而实现的,而扩展thread类则使其成为线程。

简单地把我们的接口定义为一种能力(契约),而使用 的抽象类,用于定义的框架(公共/部分)实现 它。

免责声明:下面是愚蠢的例子,尽量不要判断:-P

interface Forgiver {
    void forgive();
}

abstract class GodLike implements Forgiver {
    abstract void forget();
    final void forgive() {
        forget();
    }
}

现在你可以选择成为神一样的人,但你可以选择只成为宽恕者(即不成为神一样的人),并做:

class HumanLike implements Forgiver {
    void forgive() {
       // forgive but remember    
    }
}

或者你可以选择像上帝一样去做:

class AngelLike extends GodLike {
    void forget() {
       // forget to forgive     
    }
}

P.S.与java 8接口也可以有静态以及默认(可重写实现)方法,因此区别b/w接口和抽象类甚至更窄。

你的解释看起来还不错,但可能看起来像是你从课本上读的?: - /

我更关心的是,你的例子有多可靠?你是否费心去包括抽象和接口之间几乎所有的区别?

就我个人而言,我建议这个链接: http://mindprod.com/jgloss/interfacevsabstract.html#TABLE

对于差异的详尽列表..

希望它能帮助你和所有其他读者在未来的采访