我何时必须使用接口而不是抽象类?
我想知道什么时候应该使用接口。
让我们思考以下几点:
public abstract class Vehicle { abstract float getSpeed(); }
和:
public interface IVehicle { float getSpeed(); }
我可以很容易地实现他们两个,他们有相同的function…但我也可以添加一些variables,我的车辆类,这可能应该用在车辆(maxSpeed,carType …)
什么是使用接口的原因?
谢谢!
编辑:我发现了另一个线程中的一个不错的链接: http : //www.thecoldsun.com/en/content/01-2009/abstract-classes-and-interfaces
从Java如何编程抽象类:
因为它们只被用作inheritance层次结构中的超类,所以我们把它们称为抽象超类。 这些类不能用于实例化对象,因为抽象类是不完整的。 子类必须声明“缺less的部分”成为“具体”类,从中你可以实例化对象。 否则,这些子类也是抽象的。
回答你的问题“使用接口的原因是什么?”:
抽象类的目的是提供一个适当的超类,其他类可以inheritance,从而共享一个共同的devise。
与界面相反:
一个接口描述了一组可以在一个对象上调用的方法,但是并没有为所有的方法提供具体的实现 …一旦一个类实现了一个接口,那么这个类的所有对象都与接口types具有is-a关系并且该类的所有对象都保证提供接口描述的function。 这个类的所有子类也是如此。
所以,要回答你的问题“我想知道什么时候应该使用接口”,我想你应该使用接口,当你想要一个完整的实现,并使用抽象类,当你想为你的devise部分件(为可重用性)
从Oracle教程 :
与接口不同, 抽象类可以包含非 static
和final
字段 ,并且可以包含实现的方法。 这样的抽象类与接口类似,不同之处在于它们提供了部分实现,而将其留给子类来完成实现。 如果抽象类仅包含抽象方法声明,则应该将其声明为接口。
可以通过类层次结构中任何位置的类来实现多个接口 ,无论它们是否以任何方式相互关联。 例如,考虑可Comparable
或可Cloneable
。
相比之下, 抽象类通常被分类以分享实现 。 一个抽象类被类似的类所分类,这些类有很多共同点(抽象类的实现部分),但也有一些不同(抽象方法)。
你应该使用哪个抽象类或接口?
如果这些语句适用于您的情况, 请考虑使用抽象类 :
你想在几个密切相关的类中分享代码。
您期望扩展抽象类的类具有许多常用的方法或字段,或者需要公共访问修饰符(例如protected和private)。
您想要声明非静态或非最终字段。 这使您可以定义可以访问和修改它们所属对象状态的方法。
如果以下任何一种语句适用于您的情况, 请考虑使用接口 :
你期望不相关的类将实现你的接口。 例如,Comparable和Cloneable接口是由许多不相关的类实现的。
您想要指定特定数据types的行为,但不关心谁实现其行为。
你想利用types的多重inheritance。
许多情况下都可以在两个类中实现。
当你想定义一个至less具有基本function的类时,接口是有用的。 就像一个真正的接口,例如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; } }
有很多次您可能会考虑通过抽象实现来使用接口
- 当可用的抽象实现不能做你想要的,你想创build自己的
- 当你有一个现有的类(从其他类扩展),你想实现接口的function
一般来说,介绍接口是为了克服缺乏多重inheritance等
自Java 8发布以来,在接口中默认方法的支持下,接口类和抽象类之间的差距已经减小,但是它们仍然存在很大差异。
-
接口中的variables是public static final 。 但是抽象类可以有其他types的variables,如private,protected等
-
接口中的方法是public或public static,但抽象类中的方法也可以是private和protected
-
使用抽象类来build立相关对象之间的关系。 使用接口build立无关类之间的关系。
看看这篇文章的特殊属性的接口在Java 8中。静态修改器的默认方法在接口导致编译时错误导出错误,如果你想使用@覆盖。
本文解释了为什么在java 8中引入了默认方法: 为了增强Java 8中的Collections API以支持lambdaexpression式。
看一下oracle文档也是为了更好的理解差异。
用代码示例来看看这个相关的SE问题来更好地理解事物:
我应该如何解释一个接口和一个抽象类的区别?
引用博客: https : //mybolder.com/2015/12/02/when-to-use-abstract-class-and-intreface/
你应该使用哪个抽象类或接口?
如果这些语句适用于您的情况,请考虑使用抽象类:
- 你想在几个密切相关的类中分享代码。
- 您期望扩展抽象类的类具有许多常用的方法或字段,或者需要公共访问修饰符(例如protected和private)。
- 您想要声明非静态或非最终字段。 这使您可以定义可以访问和修改它们所属对象状态的方法。
如果以下任何一种语句适用于您的情况,请考虑使用接口:
- 你期望不相关的类将实现你的接口。 例如,Comparable和Cloneable接口是由许多不相关的类实现的。
- 您想要指定特定数据types的行为,但不关心谁实现其行为。
- 你想利用types的多重inheritance。
JDK中的抽象类的一个例子是AbstractMap ,它是Collections Framework的一部分。 它的子类(包括HashMap , TreeMap和ConcurrentHashMap )共享AbstractMap定义的许多方法(包括get , put , isEmpty , containsKey和containsValue )。
考虑到Java:
接口:
- 是一个基本的面向对象抽象。
- 经常(但不总是)比抽象类产生更清晰的代码。
- 可以通过多个具体的类来实现,以适应不同的情况。
- 可以直接实现调用多重inheritance的场景。
- 可以更容易地嘲笑出于testing目的。
- 对JDK代理有用(请参阅java.lang.reflect.Proxy)。
这些仅仅是界面与抽象类的优点/缺点列表的开始。
这是Bruce Eckel出色的书“ Thinking in Java ”的直接摘录。
[…]你应该使用一个接口还是一个抽象类 ?
那么,一个接口给你一个抽象类的好处和一个接口的好处,所以如果可以创build你的基类没有任何方法定义或成员variables,你应该总是喜欢接口抽象类。
事实上,如果你知道什么是基类,你的第一select应该是把它变成一个接口,并且只有当你被强制拥有方法定义或者成员variables的时候,你才应该把它变成一个抽象类。
当你想为一组子类定义一个模板时,使用一个抽象类,并且至less有一些调用子类的实现代码可以使用。
如果要定义其他类可以播放的angular色 ,请使用接口 , 而不pipe这些类在inheritance树中的位置
你扩展一个抽象类
你实现一个接口:)
在一个接口中,所有的字段都是自动public
static
final
,所有的方法都是public
而抽象类允许你在这里有一些灵活性。
抽象类可以包含非抽象的方法,而在接口中,所有的方法都是抽象的,必须实现。
你应该使用接口,而你知道你总是会实现这些特定的方法。 你也可以从多个接口inheritance,这是java处理多重inheritance的方法
界面基本上是在双方协同工作时使用的,一方要隐藏其他方面的东西(或者只想显示他的一部分)。 在jdbc jdbc供应商提供给我们一些接口bcoz他们想要隐藏我们所有的东西。
抽象类只在这种情况下使用,当我们要支持一个以上的类的共同行为…或者想提供一些未实现的方法(方法应该是抽象的)的预先实现的实现。 例如。 servlet接口中的http servlet是一个抽象类bcoz这个类实现了servlet接口,除了它的服务方法…所以这个类帮助我们得到一些接口方法的preimplemetation …
其实Interface和抽象类只是用来指定一些合约/规则,这些合约/规则只会显示其子类将如何。
大多数情况下,我们知道接口是一个纯粹的抽象。意味着你不能指定一个单一的方法与body.This特别的一点是抽象类的优点。抽象类中的手段有权指定方法与身体和身体没有好。
所以,如果你想指定关于你的子类的东西,那么你可以去接口。 但是,如果你也想为你的子类指定一些东西,你也希望你的类也应该有自己的方法。那么在这种情况下,你可以去抽象类
你不能实现与抽象类的多重inheritance,这就是为什么太阳微系统提供接口。
您不能扩展两个类,但可以实现多个接口
Interface
和Abstract Class
是实现OOP语言抽象的两种不同方式。
接口提供了100%
抽象,即所有的方法都是抽象的。
抽象类提供了0 to 100%
抽象,即它可能有或没有抽象方法。
当我们希望客户端实现一个types的所有function时,我们可以使用Interface
。
当Abstract Class
实现者可以提供一些通用的function时,我们可以使用Abstract Class
,客户端将有机会实现他实际需要的东西。
抽象类 :当强壮的时候使用它是超类和子类的关系,而所有的子类都有一些共同的行为。
接口 :它定义了所有子类需要遵循的协议。
这个问题的答案很简单,无论我们能用接口做什么,都可以用抽象类Agree来完成……所以何时使用接口,答案就在于C#对多重inheritance的限制。 当你只有合同(摘要)来声明,并希望你的子类实现它与接口,因为如果你在这种情况下使用抽象类,你不能从一个类inheritance,你被卡住,如果要从一个inheritance更多的类,但你可以实现尽可能多的接口。
如果您使用的是JDK 8,那么就没有理由使用抽象类,因为无论我们使用抽象类,我们现在都可以使用接口来执行它,因为使用了默认方法。 如果你使用抽象类,你必须扩展它,并且有一个限制,只能扩展一次。 但是,如果你使用接口,你可以实现尽可能多的,你想要的。
接口默认是一个抽象类,所有的方法和构造函数都是公共的。
接口和抽象类看起来非常相似,但是它们之间有重要的区别。
抽象是build立在一个好的“ 是 ”关系的基础上的。 这意味着你会说一辆汽车是本田,而本田是一辆汽车。 对类使用抽象意味着你也可以有抽象方法。 这将需要从它扩展的任何子类来获取抽象方法并覆盖它们。 使用下面的例子,我们可以创build一个抽象的howToStart(); 方法,这将需要每个类来实现它。
通过抽象,我们可以提供代码之间的相似性,所以我们仍然有一个基类。 以Car类的想法为例,我们可以创build:
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(); }
然后,与本田class,我们会有:
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 } }
接口基于“有-a”关系。 这意味着你可以说一辆车有一台发动机,但是一台发动机不是一辆汽车。 在上面的例子中,本田已经implements Engine
。
对于引擎接口,我们可以创build:
public interface Engine { public void startup(); }
该界面将提供多对一的实例。 所以我们可以将引擎接口应用于任何types的汽车。 我们也可以把它扩展到其他对象。 就像我们要做一个船class,并且有一些船的子类,我们可以扩展Engine,并且让子类的船需要startup();
方法。 接口对于为具有一些相似性的各种类创build框架是很好的。 我们也可以在一个类中实现多个实例,比如:
public class Honda extends implements Engine, Transmission, List<Parts>
希望这有助于。
如果您的Interface方法实现对所有Inherting类都是相同的,那么您不需要接口,而应该使用Abstract类。 当你想要某个东西被每个类(必须)跟随,那里的实现将会有所不同或者没有被定义,那么我们去接口。