对于以上大部分帖子,我持有不同意见(抱歉!如果你想的话可以将我降级:-))
首先,“只有一个超类”的答案是无聊的。在面试中给我这个答案的人很快就会被反驳:“C++存在于Java之前,而且C++有多个超类。为什么你认为James Gosling只允许Java有一个超类?”
理解你回答背后的哲学,否则你就完蛋了(至少如果我面试你的话)。
其次,接口比抽象类有多种优势,特别是在设计接口时。最大的优势是不会对方法调用者强加特定的类结构。没有什么比尝试使用要求特定类结构的方法调用更糟糕的了。它很痛苦和尴尬。使用接口,任何东西都可以传递给方法,期望值最小。
例如:
public void foo(Hashtable bar);
对比。
public void foo(Map bar);
对于前者,调用者将始终采取其现有数据结构并将其插入到新的Hashtable中。
第三,接口允许具体类实现者中的公共方法变为“私有”。如果该方法未在接口中声明,则不能使用(或误用)该方法的类。这就带来了第四点……
第四,接口代表实现类和调用者之间的最小契约。这个最小契约确切地指定了具体的实现者期望如何被使用,而不再多余。调用类不允许使用接口“契约”未指定的任何其他方法。所使用的接口名称也影响开发人员对他们应该如何使用对象的期望。如果开发人员传递一个
public interface FragmentVisitor {
public void visit(Node node);
}
开发人员知道他们唯一可以调用的方法是 visit 方法。他们不会被具体类中那些不应该乱动的亮闪闪的方法所分心。
最后,抽象类有许多方法,这些方法实际上只存在于子类中供其使用。因此,抽象类对于外部开发人员来说有点像一团乱麻,没有指导哪些方法是打算供外部代码使用的。
当然,有些方法可以设置为 protected。然而,可悲的是,protected 方法也对同一包中的其他类可见。如果抽象类的方法实现了接口,则该方法必须是公共的。
然而,使用接口可以将所有这些内部细节安全地隐藏起来,既不会看到抽象超类或具体类中的内部细节。
当然,我知道开发人员可能会使用一些“特殊”知识将对象强制转换为另一个更广泛的接口或具体类本身。但是这样的转换违反了预期的合同,开发人员应该被用鲑鱼拍打。