最近,我接受了两次电话采访,有人问我接口和抽象类之间的区别。 我已经解释了我能够想到的各个方面,可是彷佛他们正在等我说起一些特定的内容,我不知道它是什么。 php
根据个人经验,我认为如下是对的。 若是我缺乏要点,请告诉我。 html
接口: java
接口中声明的每一个方法都必须在子类中实现。 接口中只能存在事件,委托,属性(C#)和方法。 一个类能够实现多个接口。 面试
抽象类: oracle
子类只须要实现Abstract方法。 Abstract类能够具备实现的常规方法。 抽象类在事件,委托,属性和方法旁边也能够具备类变量。 因为C#中不存在多重继承,一个类只能实现一个抽象类。 ide
毕竟,面试官提出了一个问题:“若是您有一个仅包含抽象方法的Abstract类,该怎么办?与接口有什么不一样?” 我不知道答案,但我认为这是上面提到的继承对吗? 函数
另外一个面试官问我,若是接口内有一个Public变量,那和Abstract Class有什么不一样? 我坚持认为,接口内不能有公共变量。 我不知道他想听什么,但他也不满意。 工具
另请参阅 : ui
简介:抽象类用于对外观类似的类的类层次进行建模 (例如Animal能够是抽象类,而Human,Lion,Tiger能够是具体派生类)
和
接口用于2个类似/不类似类之间的通讯 ,这些类不关心实现接口的类的类型(例如,高度能够是接口属性,能够由Human,Building,Tree来实现。是否能够食用,您能够游泳,能够死去或其余任何事情。.只重要于您须要具备Height的东西(在您的课堂中实施))。
尽管这个问题已经很老了,但我想补充一点,以支持接口:
可使用任何依赖关系注入工具来注入接口,其中不多有人支持Abstract类注入。
回答第二个问题: public
在定义的变量interface
是static final
默认,而public
在变量abstract
类是一个实例变量。
遗产
考虑一下汽车和公共汽车。 他们是两种不一样的车辆。 可是它们仍然具备一些共同的特性,例如具备转向器,制动器,齿轮,发动机等。
所以,使用继承概念,能够将其表示为...
public class Vehicle { private Driver driver; private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections). //You can define as many properties as you want here ... }
如今是自行车...
public class Bicycle extends Vehicle { //You define properties which are unique to bicycles here ... private Pedal pedal; }
还有一辆车...
public class Car extends Vehicle { private Engine engine; private Door[] doors; }
这就是继承 。 如上所述,咱们使用它们将对象分类为更简单的基本形式及其子对象。
抽象类
抽象类是不完整的对象。 为了进一步理解它,让咱们再次考虑车辆的类比。
能够驾驶车辆。 对? 可是,不一样的车辆以不一样的方式行驶。例如,您不能像驾驶自行车同样驾驶汽车。
那么如何表现车辆的驱动功能呢? 很难检查它是什么类型的车辆并以其自身的功能驾驶它; 您必须在添加新型车辆时一次又一次地更改Driver类。
这里是抽象类和方法的做用。 您能够将drive方法定义为抽象,以告诉每一个继承的子代必须实现此功能。
所以,若是您修改车辆类别...
//......Code of Vehicle Class abstract public void drive(); //.....Code continues
自行车和汽车还必须指定如何驾驶。 不然,代码将没法编译,并引起错误。
简而言之,抽象类是具备某些不完整功能的部分不完整类,继承子级必须指定它们本身的功能。
接口接口彻底不完整。 它们没有任何属性。 他们只是代表继承的孩子有能力作某事...
假设您有不一样类型的手机。 它们每一个都有不一样的方式来执行不一样的功能。 例如:打电话给一我的。 手机的制造商会指定如何进行。 手机能够在此处拨打号码-便可以拨打。 让咱们将其表示为接口。
public interface Dialable { public void dial(Number n); }
在这里,“可拨号”的制造商定义了如何拨打号码。 您只须要给它拨一个号码便可。
// Makers define how exactly dialable work inside. Dialable PHONE1 = new Dialable() { public void dial(Number n) { //Do the phone1's own way to dial a number } } Dialable PHONE2 = new Dialable() { public void dial(Number n) { //Do the phone2's own way to dial a number } } //Suppose there is a function written by someone else, which expects a Dialable ...... public static void main(String[] args) { Dialable myDialable = SomeLibrary.PHONE1; SomeOtherLibrary.doSomethingUsingADialable(myDialable); } .....
所以,使用接口而不是抽象类,使用Dialable的函数的编写者无需担忧其属性。 例如:它有触摸屏或拨号盘吗?是固定座机仍是移动电话。 您只须要知道它是否可拨号便可。 它是否继承(或实现)了Dialable接口。
更重要的是 ,若是有一天您将Dialable切换为其余
...... public static void main(String[] args) { Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2 SomeOtherLibrary.doSomethingUsingADialable(myDialable); } .....
您能够确保代码仍然能够正常工做,由于使用可拨号功能的功能不(也不能)依赖于“可拨号”界面中指定的详细信息。 它们都实现了Dialable接口,而这只是该函数所关心的。
开发人员一般使用接口来确保对象之间的互操做性(可互换使用),只要它们具备共同的功能(就像您可能须要更换座机或移动电话同样,只要您拨打一个号码便可)。 简而言之,接口是抽象类的简单得多的版本,没有任何属性。
另外,请注意,您能够实现(继承)任意数量的接口,但只能扩展(继承)单个父类。
更多信息 抽象类与接口
After all that, the interviewer came up with the question "What if you had an Abstract class with only abstract methods? How would that be different from an interface?"
Docs清楚地指出,若是抽象类仅包含抽象方法声明,则应将其声明为接口。
An another interviewer asked me what if you had a Public variable inside the interface, how would that be different than in Abstract Class?
默认状况下,接口中的变量是public static和final。 若是抽象类中的全部变量都是公共的,该问题可能会被框起来? 好吧,它们仍然能够是非静态的和非最终的,与接口中的变量不一样。
最后,我还要对上述提到的一点再加一点-抽象类仍然是类,而且属于单个继承树,而接口能够存在于多个继承中。