我最近参加了一次采访,他们问我"为什么接口比抽象类更受欢迎?"
我尝试给出一些答案,如:
我们只能获得一个Extends功能
他们是100%抽象
实施不是硬编码的
他们让我带走你使用的任何JDBC api."为什么他们是接口?".
我可以为此得到更好的答案吗?
面试问题反映了提问者的某种信念.我相信这个人是错的,因此你可以选择其中一个方向.
给他们想要的答案.
恭敬地不同意.
他们想要的答案,嗯,其他海报突出了那些令人难以置信的好.多接口继承,继承强制类做出实现选择,接口可以更容易地更改.
但是,如果您在分歧中创建引人注目(且正确)的论点,那么面试官可能会注意到.首先,强调关于接口的积极的事情,这是必须的.其次,我会说接口在许多情况下都更好,但它们也导致代码重复,这是一个负面的事情.如果您有大量的子类,它们将在很大程度上执行相同的实现,以及额外的功能,那么您可能需要一个抽象类.它允许您拥有许多具有细粒度细节的类似对象,而只有接口,您必须拥有许多不同的对象,几乎重复的代码.
接口有很多用途,并且有令人信服的理由相信它们"更好".但是,您应始终使用正确的工具来完成作业,这意味着您无法注销抽象类.
一般来说,这绝不是一个应该盲目遵循的"规则",最灵活的安排是:
interface abstract class concrete class 1 concrete class 2
界面有几个原因:
已扩展的现有类可以实现接口(假设您可以控制现有类的代码)
现有的类可以是子类,子类可以实现接口(假设现有的类是可子类化的)
这意味着您可以使用预先存在的类(或者只是必须从其他类扩展的类)并使它们与您的代码一起使用.
抽象类用于提供具体类的所有公共位.从编写新类或修改要扩展它的类时开始扩展抽象类(假设它们从java.lang.Object扩展).
您应该始终(除非您有充分的理由不)将变量(实例,类,本地和方法参数)声明为接口.
你只能获得一次继承.如果您创建一个抽象类而不是一个接口,那么继承您的类的人也不能继承另一个抽象类.
您可以实现多个接口,但只能从单个类继承
抽象类
1.不能独立于派生类进行实例化.抽象类构造函数仅由其派生类调用.
2.定义基类必须实现的抽象成员签名.
3.比接口更具可扩展性,不会破坏任何版本兼容性.使用抽象类,可以添加所有派生类都可以继承的其他非抽象成员.
4.可以包括存储在字段中的数据.
5.允许具有实现的(虚拟)成员,因此,为派生类提供成员的默认实现.
6.从抽象类中获取使用了一个子类的唯一基类选项.
接口
1.无法实例化.
2.接口的所有成员的实现发生在基类中.在实现类中只能实现一些成员是不可能的.
3.使用其他成员扩展接口会破坏版本兼容性.
4.无法存储任何数据.只能在派生类上指定字段.解决方法是定义属性,但没有实现.
5.所有成员都是自动虚拟的,不能包含任何实现.
6.虽然不会出现默认实现,但实现接口的类可以继续相互派生.
当devinb和其他人提到时,听起来像面试官表示他们不接受你的有效答案而无知.
但是,提到JDBC可能是一个暗示.在这种情况下,也许他们要求客户端编码对接口而不是类的好处.
因此,他们可能正在寻找更像"将客户与特定实现分离"的答案,而不是完全有效的答案,例如"你只使用一次继承",这与课堂设计有关.
抽象类有许多潜在的缺陷.例如,如果重写方法,则super()
除非显式调用该方法,否则不会调用该方法.这可能会导致实现不良的重写类出现问题.此外,equals()
使用继承时可能存在问题.
当您想要共享实现时,使用接口可以鼓励使用组合.组合通常是重用其他对象的更好方法,因为它不那么脆弱.继承很容易被滥用或用于错误的目的.
定义一个接口是一个非常安全的定义对象应该如何行事,而不会危及该脆性方式可以配备扩展了另一个类,抽象的或没有.
另外,正如您所提到的,您一次只能扩展一个类,但您可以根据需要实现任意数量的接口.