90

我想知道什么时候应该使用接口。

让我们考虑以下几点:

public abstract class Vehicle {
   abstract float getSpeed();
}

和 :

public interface IVehicle {
  float getSpeed();
}

我可以轻松实现它们,它们具有相同的功能......但我也可以向我的车辆类添加一些变量,这可能应该在车辆中使用(maxSpeed,carType......)

使用接口的原因是什么?

谢谢!

编辑:我在另一个线程中找到了一个很好的链接:http ://www.thecoldsun.com/en/content/01-2009/abstract-classes-and-interfaces

4

18 回答 18

112

Java How to Program关于抽象类:

因为它们仅在继承层次结构中用作超类,所以我们将它们称为抽象超类。这些类不能用于实例化对象,因为抽象类是不完整的。 子类必须声明“缺失的部分”才能成为“具体”类,您可以从中实例化对象。否则,这些子类也将是抽象的。

要回答您的问题“使用接口的原因是什么?”:

抽象类的目的是提供一个合适的超类,其他类可以从该超类继承,从而共享一个共同的设计。

与接口相反:

接口描述了可以在对象上调用的一组方法,但不提供所有方法的具体实现......一旦类实现了接口,该类的所有对象都与接口类型具有is-a关系,并且该类的所有对象都保证提供接口描述的功能。该类的所有子类也是如此。

因此,要回答您的问题“我想知道何时应该使用接口”,我认为您应该在需要完整实现时使用接口,而在需要部分设计时使用抽象类(为了可重用性)

于 2013-05-27T22:46:25.347 回答
18

来自Oracle 教程

与接口不同,抽象类可以包含不是 staticand的字段final,并且它们可以包含实现的方法。这种抽象类类似于接口,只是它们提供了部分实现,将其留给子类来完成实现。如果抽象类仅包含抽象方法声明,则应将其声明为接口。

多个接口可以由类层次结构中任何位置的类实现,无论它们是否以任何方式相互关联。想想Comparableor Cloneable,例如。

相比之下,抽象类最常被子类化以共享实现部分。单个抽象类由具有许多共同点(抽象类的实现部分)但也有一些差异(抽象方法)的类似类子类化。

于 2013-05-27T22:33:47.147 回答
11

许多情况可以在这两种类类型中实现。

当您要定义一个必须至少具有基本功能的类时,接口很有用。就像一个真实的接口,例如 USB。

interface USB {
    public function sendPower(); //charge iphone for example
    public function sendData(); //itunes
    public function recieveData();
}

当有多种实现对象的方法时,请使用抽象类。

abstract class MobilePhone {
    public function isIphone();

    public function charge() {
        //get some power, all phones need that
    }
}

class iPhone extends MobilePhone {
    public function isIphone() { return true; }
}
于 2013-05-27T22:43:32.023 回答
7

有很多次你可能会考虑在抽象实现上使用接口

  • 当可用的抽象实现不能满足您的要求并且您想创建自己的抽象实现时
  • 当您有一个现有的类(从其他类扩展)并且您想要实现接口的功能时

一般来说,引入接口是为了克服缺乏多重继承等问题

于 2013-05-27T22:36:03.477 回答
5

自 Java 8 发布以来,接口中支持默认方法,接口抽象类之间的差距已经缩小,但它们仍然存在重大差异。

  1. 接口中的变量是public static final。但抽象类可以有其他类型的变量,如私有、受保护

  2. 接口中的方法是公共的或公共静态的,但抽象类中的方法也可以是 私有受保护的

  3. 使用抽象类建立相互关联的对象之间的关系。使用接口在不相关的类之间建立关系。

查看这篇文章以了解 java 8 中接口的特殊属性。如果要使用 @override,接口中默认方法的静态修饰符会导致派生错误中的编译时错误。

本文解释了为什么在 java 8 中引入了默认方法: 增强 Java 8 中的 Collections API 以支持 lambda 表达式。

也请查看oracle文档以更好地了解差异。

用代码示例查看这个相关的 SE 问题,以更好地理解事物:

我应该如何解释接口和抽象类之间的区别?

于 2015-11-27T12:09:42.843 回答
5

摘自Java™ 教程 - 抽象类与接口的比较

您应该使用哪个抽象类或接口?

  • 如果这些陈述中的任何一个适用于您的情况,请考虑使用抽象类:
    • 您希望在几个密切相关的类之间共享代码。
    • 您希望扩展抽象类的类具有许多公共方法或字段,或者需要除公共之外的访问修饰符(例如受保护和私有)。
    • 您要声明非静态或非最终字段。这使您能够定义可以访问和修改它们所属对象的状态的方法。
  • 如果这些陈述中的任何一个适用于您的情况,请考虑使用接口:
    • 您希望不相关的类会实现您的接口。例如,接口ComparableCloneable由许多不相关的类实现。
    • 您想指定特定数据类型的行为,但不关心谁实现了它的行为。
    • 您想利用类型的多重继承。

JDK 中抽象类的一个示例是AbstractMap,它是 Collections Framework 的一部分。它的子类(包括HashMapTreeMapConcurrentHashMap)共享许多定义的方法(包括getputisEmptycontainsKeycontainsValueAbstractMap

于 2016-06-03T10:39:10.153 回答
4

当您想为一组子类定义模板时,请使用抽象类,并且您至少有一些调用子类可以使用的实现代码。

当您想要定义其他类可以扮演的角色时使用接口,无论这些类在继承树中的什么位置

扩展了一个抽象类

实现了一个接口:)

接口中,所有字段都是自动的public static final,所有方法都是自动的,public抽象类在这里允许您有一点灵活性。

于 2016-07-20T20:30:15.030 回答
2

这是Bruce Eckel的优秀著作“ Thinking in Java ”的直接摘录。

[..] 你应该使用接口还是抽象类

好吧,接口给你带来了抽象类的好处和接口的好处,所以如果可以在没有任何方法定义或成员变量的情况下创建你的基类,你应该总是更喜欢接口而不是抽象类。

事实上,如果你知道某个东西将成为一个基类,那么你的第一选择应该是让它成为一个接口,并且只有当你被迫拥有方法定义或成员变量时,你才应该更改为抽象类。

于 2016-11-04T03:09:56.233 回答
1

考虑Java:

接口:

  • 是一个基本的 OOP 抽象。
  • 通常(但不总是)会产生比抽象类更清晰的代码。
  • 可以通过多个具体的类来实现,以适应不同的情况。
  • 可以直接实现需要多继承的场景。
  • 可以更容易地模拟出来以进行测试。
  • 对 JDK 代理很有用(参见 java.lang.reflect.Proxy)。

这些只是接口与抽象类的一长串优缺点的开始。

于 2013-05-27T22:44:58.440 回答
1

这个问题的答案很简单,我们可以用接口做什么都可以用抽象类Agree...所以什么时候使用接口,答案就在于C#对多重继承的限制。当您只有要声明的合同(摘要)并希望您的子类实现它时,它与接口一起使用,因为如果在这种情况下使用抽象类,则不能从另一个类继承,如果想从一个继承,您会被卡住更多的类,但你可以实现尽可能多的接口。

于 2017-06-03T20:06:10.940 回答
1

如果您使用的是 JDK 8,则没有理由使用抽象类,因为无论我们对抽象类做什么,我们现在都可以使用接口来完成,因为默认方法。如果您使用抽象类,则必须对其进行扩展,并且存在只能扩展一次的限制。但是,如果您使用接口,则可以实现任意数量的。

默认情况下,接口是一个抽象类,所有方法和构造函数都是公共的。

于 2017-08-16T18:22:03.680 回答
0

抽象类可以包含非抽象的方法,而在接口中,所有方法都是抽象的并且必须实现。

当您知道您将始终实现这些特定方法时,您应该使用接口。你也可以从多个接口继承,这是java处理多重继承的方式

于 2013-05-27T22:36:47.833 回答
0

当两方一起工作时,基本上使用界面,并且一方想要对另一方隐藏某些东西(或只想显示他的类的某些部分)。而不是我们使用界面,例如。在 jdbc 中,jdbc 供应商为我们提供了一些接口,因为他们想对我们隐藏一切。

抽象类仅在我们想要支持多个类中的常见行为时使用......或者想要提供一些带有一些未实现方法的预实现实现(方法应该是抽象的)。例如。servlet接口中的http servlet是一个抽象类bcoz这个类实现了servlet接口,除了它的服务方法......所以这个类帮助我们获得一些接口方法的预实现......

于 2014-03-03T14:48:45.827 回答
0

实际上,接口和抽象类仅用于指定一些合同/规则,这些合同/规则将显示它们的子类将如何。

大多数情况下,我们知道接口是纯抽象的。意味着你不能用body指定单个方法。这一点是抽象类的优点。抽象类中的意思是你有权指定带body和不带body的方法。

因此,如果您想指定有关您的子类的内容,则可以选择接口。但是,如果您还想为您的子类指定一些东西,并且您还希望您的类也应该有一些自己的方法。那么在这种情况下,您可以选择抽象类

于 2014-04-01T07:18:05.553 回答
0

抽象类无法实现多重继承,这就是 Sun Microsystems 提供接口的原因。

您不能扩展两个类,但可以实现多个接口。

于 2015-03-20T14:06:58.113 回答
0

Interface并且Abstract Class是在 OOP 语言中实现抽象的两种不同方法。

接口提供100%抽象,即所有方法都是抽象的。

抽象类提供0 to 100%抽象,即它可能有也可能没有抽象方法。

Interface当我们希望客户端实现一个类型的所有功能时,我们可以使用它。

Abstract Class当实现者可以提供一些通用功能Abstract Class并且客户将有机会实现他实际需要的东西时,我们可以使用。

于 2016-07-19T19:19:24.790 回答
0

抽象类:当超类和子类之间存在强is-a关系并且所有子类共享一些共同行为时使用它。

接口:它只定义所有子类需要遵循的协议。

于 2016-10-06T06:10:02.957 回答
0

接口和抽象类看起来非常相似,但是它们之间有重要的区别。

抽象基于良好的“ is-a ”关系。这意味着您会说汽车是本田,而本田是汽车。在类上使用抽象意味着您也可以拥有抽象方法。这将需要从它扩展的任何子类来获取抽象方法并覆盖它们。使用下面的示例,我们可以创建一个抽象的 howToStart(); 需要每个类来实现它的方法。

通过抽象,我们可以提供代码之间的相似性,因此我们仍然有一个基类。使用 Car 类想法的示例,我们可以创建:

public abstract class Car{
    private String make;
    private String model

    protected Car() { }  // Default constructor

    protect Car(String make, String model){
        //Assign values to 
    }

    public abstract void howToStart();
}

然后有了本田课程,我们将拥有:

public class Honda extends implements Engine {

    public Honda() { }  // Default constructor

    public Honda(String make, String model){
        //Assign values
    }

    @Override
    public static void howToStart(){
        // Code on how to start
    }

}

接口基于“has-a”关系。这意味着你可以说汽车有引擎,但引擎不是汽车。在上面的例子中,本田有implements Engine.

对于引擎接口,我们可以创建:

public interface Engine {
    public void startup();
}

该接口将提供一个多对一的实例。所以我们可以将 Engine 接口应用于任何类型的汽车。我们还可以将其扩展到其他对象。就像我们要创建一个小船类,并且有小船类型的子类,我们可以扩展引擎并让小船的子类需要该startup();方法。接口有利于为具有某些相似性的各种类创建框架。我们还可以在一个类中实现多个实例,例如:

public class Honda extends implements Engine, Transmission, List<Parts>

希望这会有所帮助。

于 2016-11-04T23:13:40.820 回答