我想知道何时应该使用接口。
让我们考虑以下事项:
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
答案 0 :(得分:95)
从Java How to Program关于抽象类:
因为它们仅用作继承层次结构中的超类, 我们将它们称为抽象超类。 这些课程不可能 用于实例化对象,因为抽象类是不完整的。 子类必须声明“缺失部分”成为“具体”类, 您可以从中实例化对象。否则,这些子类也是如此 将是抽象的。
回答你的问题“使用接口的原因是什么?”:
抽象类的目的是提供适当的超类 其他类可以从中继承并共享一个共同的设计。
与界面相反:
接口描述一组可在其上调用的方法 对象,但不提供所有的具体实现 方法 ...一旦类实现了一个接口,该类的所有对象都有 与接口类型的is-a关系,以及的所有对象 class保证提供由...描述的功能 接口。对于该类的所有子类也是如此。
因此,为了回答你的问题“我想知道何时应该使用接口”,我认为你应该在需要完整实现时使用接口,并在需要部分设计(可重用性)时使用抽象类
答案 1 :(得分:15)
来自Oracle tutorials :
与接口不同,抽象类可以包含非 static
和final
的字段,并且它们可以包含已实现的方法。这些抽象类与接口类似,不同之处在于它们提供部分实现,将其留给子类来完成实现。如果抽象类只包含抽象方法声明,则应将其声明为接口。
可以通过类层次结构中的任何位置实现多个接口,无论它们是否以任何方式彼此相关。例如,可以考虑Comparable
或Cloneable
。
相比之下,抽象类最常被子类化以共享实现。单个抽象类由具有许多共同点的类似类(抽象类的实现部分)进行子类化,但也有一些差异(抽象方法)。
答案 2 :(得分:8)
许多情况都可以在两种类型中实现。
当您想要定义必须至少具有基本功能的类时,接口非常有用。就像一个真实的接口,例如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; }
}
答案 3 :(得分:7)
您可能会多次考虑在抽象实现上使用接口
一般来说,引入接口是为了克服缺乏多重继承性等问题
答案 4 :(得分:3)
自Java 8发布以来,界面支持默认方法,接口和抽象类之间的差距已经缩小,但仍然存在重大差异。
界面中的变量为 public static final 。但抽象类可以有其他类型的变量,如 private,protected 等
界面中的方法是公开或公共静态,但抽象类中的方法可以是私有和受保护强>太
使用抽象类来建立相互关联的对象之间的关系。使用界面来建立不相关的类之间的关系。
对于java中的 interface 的特殊属性,请查看此article。如果要使用@override,接口中的默认方法的静态修饰符会导致派生错误中的编译时错误
本文解释了为什么在java 8中引入了默认方法:在Java 8中增强Collections API以支持lambda表达式。
还要查看oracle文档,以更好的方式理解差异。
通过代码示例查看这些相关的SE问题,以便更好地理解事物:
How should I have explained the difference between an Interface and an Abstract class?
答案 5 :(得分:3)
来自The Java™ Tutorials - Abstract Classes Compared to Interfaces
您应该使用哪些,抽象类或接口?
- 如果这些语句中的任何一个适用于您的情况,请考虑使用抽象类:
- 您希望在几个密切相关的类之间共享代码。
- 您希望扩展抽象类的类具有许多常用方法或字段,或者需要除公共之外的访问修饰符(例如protected和private)。
- 您想要声明非静态或非最终字段。这使您可以定义可以访问和修改它们所属对象状态的方法。
- 如果这些陈述中的任何一个适用于您的情况,请考虑使用接口:
- 您希望不相关的类会实现您的界面。例如,接口
Comparable
和Cloneable
由许多不相关的类实现。- 您希望指定特定数据类型的行为,但不关心谁实现其行为。
- 您希望利用类型的多重继承。
JDK中抽象类的一个示例是
AbstractMap
,它是集合框架的一部分。其子类(包括HashMap
,TreeMap
和ConcurrentHashMap
)共享许多方法(包括get
,put
,isEmpty
,{{1 {}}}定义的{}}和containsKey
}。
答案 6 :(得分:2)
如果要为一组子类定义模板,请使用抽象类,至少要有一些实现代码调用子类可以使用。
如果要定义其他类可以播放的角色,请使用界面 ,无论这些类在继承树中的位置
你扩展抽象类
您实施接口:)
在界面中,所有字段都会自动public
static
final
,所有方法都是public
而抽象类可以让你在这里有一点灵活性。
答案 7 :(得分:1)
考虑Java:
接口:
这些只是接口与抽象类的很长的优缺点列表的开头。
答案 8 :(得分:1)
这是优秀书籍的直接摘录' Thinking in Java'布鲁斯·埃克尔(Bruce Eckel)。
[..]你应该使用界面还是抽象类?
好吧,一个接口为您提供了抽象类的好处和接口的好处,因此如果可以创建没有任何方法定义或成员变量的基类,您应该总是更喜欢接口到抽象类。
事实上,如果您知道某些东西将成为基类,那么您的第一选择应该是使其成为一个接口,并且只有当您被迫拥有方法定义或成员变量时才应该更改为抽象类
答案 9 :(得分:1)
这个问题的答案非常简单,无论我们用接口做什么都可以用抽象类同步来完成...所以当使用接口时,答案就在于多重继承的C#限制。当你只有声明的契约(摘要)并且希望你的子类实现它时,请使用接口,因为如果你在这种情况下使用抽象类,你就不能继承另一个类,如果你想继承一个类,你就会陷入困境更多类,但你可以实现尽可能多的接口。
答案 10 :(得分:1)
如果您使用的是JDK 8,则没有理由使用抽象类,因为无论我们使用抽象类,我们现在可以使用默认方法来使用接口。 如果你使用抽象类,你必须扩展它,并且有一个限制,你只能扩展一次。但是如果你使用界面,你可以实现任意多个。
默认情况下,接口是一个抽象类,所有方法和构造函数都是公共的。
答案 11 :(得分:0)
接口基本上是在两方合作时使用的,一方希望隐藏其他东西(或者只是想显示他班级的某些部分)。然后我们使用接口例如。 在jdbc jdbc供应商为我们提供了一些bcoz接口,他们希望隐藏我们的一切。
抽象类仅在我们想要支持多个类中的公共行为时才使用...或者想要使用一些未实现的方法提供一些预先实现的实现(方法应该是抽象的)。 例如。 servlet接口中的http servlet是一个抽象类bcoz这个类实现了servlet接口,除了它的服务方法...所以这个类帮助我们得到一些预处理接口方法......
答案 12 :(得分:0)
实际上,接口和抽象类仅用于指定一些合同/规则,这些合同/规则只显示它们的子类如何。
大多数情况下,我们知道接口是一个纯粹的抽象。在那里你不能用body指定一个方法。这个特殊点是抽象类的优点。抽象类中的元素你有权用body指定方法而没有body -好。
因此,如果你想指定关于你的子类的东西,那么你可以去接口。 但是,如果你也想为你的子类指定一些东西,你也想要你的类也应该有一些自己的方法。那么在那种情况下你可以去抽象类
答案 13 :(得分:0)
您无法使用抽象类实现多重继承,这就是Sun Microsystems提供接口的原因。
您不能扩展两个类,但可以实现多个接口。
答案 14 :(得分:0)
抽象类可以包含非抽象的方法,而在接口中,所有方法都是抽象的,必须实现。
当您知道将始终实现这些特定方法时,您应该使用接口。你也可以从多个接口继承,这是java处理多重继承的方式
答案 15 :(得分:0)
Interface
和Abstract Class
是在OOP语言中实现抽象的两种不同方式。
接口提供100%
抽象,即所有方法都是抽象的。
抽象类提供0 to 100%
抽象,即它可能有或没有抽象方法。
当我们希望客户实现某种类型的所有功能时,我们可以使用Interface
。
当Abstract Class
实施者可以提供某些常用功能时,我们可以使用Abstract Class
,客户将有机会实现他实际需要的功能。
答案 16 :(得分:0)
抽象类:当超类和子类之间存在强大的is-a关系时使用它,并且所有子类都有一些共同的行为。
接口:它只定义所有子类需要遵循的协议。
答案 17 :(得分:-1)
接口和抽象类似乎非常相似,但它们之间存在重要差异。
抽象基于良好的“ 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>
希望这有帮助。