为什么界面方法没有正文
要实现多重inheritance,我们必须使用接口,但为什么接口方法没有实体,为什么必须在派生类中重写它们?
我真的想要一个清晰的答案,不涉及太多的计算机术语,我似乎无法理解这一点,我已经提到了各种参考
因为Java与C ++或Eiffel之类的语言相比,只有多种类型的inheritance(即接口和一个类),而不是状态和行为的多重inheritance。 后者增加了巨大的复杂性(尤其是国家)。
Java设计者(以及C#,就此而言)选择不包括它,因为它给C ++程序员带来了非常难以调试的问题。 通过实现多个接口,您可以解决几乎所有需要真正多重inheritance的问题,因此权衡被认为是值得的。
请注意, 行为 (非状态)的多重inheritance可能以虚拟扩展方法的forms出现在Java 8中(除非它们像许多其他事物中的一样再次推迟),其中接口可以声明委托给另一个类中的一个的方法,然后存在于实现该接口的所有类型上。
接口声明实现类提供的WHAT服务,而不是HOW(这是实现类的工作)。 多重inheritance被认为是错误的,因为它导致复杂的代码和类层次结构。
接口只有常量变量(public + static + final)和抽象方法(public和abstract)。 这些应该由实现接口的类使用。
接口简单地说’Am a contract’,如果你想使用它,应该坚持一些规则(给所有抽象方法实现)。
Java中省略了多重inheritance,确保类只能扩展1个类,以避免钻石问题 。 无论如何,您可以通过使用接口在Java中进行多种类型的inheritance。
Java接口包含必须由实现接口的类实现的方法列表。 因此,方法没有主体:每个方法的主体都在实现类中。
简单回答:
接口提供了实现标准。
说明:
在Java中,接口类似于抽象类,因为其成员未实现 。 例如,
public interface Comparable { boolean less(Object m); boolean greater(Object m); boolean lessEqual(Object m); boolean greaterEqual(Object m); }
接口提供了实现标准。
使用接口的好处是它们模拟多重inheritance 。 Java中的所有类都必须只有一个基类 ,唯一的例外是java.lang.Object
(Java类型系统的根类); java中不允许多inheritance类。
所有实例方法都是隐式public
和abstract
。 您可以将它们标记为这样,但不鼓励这样做,因为标记被认为是过时的做法 。 接口本身不需要是公共的,标准库中的几个接口不是公共的,因此仅在内部使用。
接口创建类可以实现的协议 。 请注意,可以像扩展类一样扩展接口(以获取新接口)。 实际上可以扩展几个接口 。 接口因此享有多重inheritance的好处。 ( 类没有。)接口的多重inheritance几乎没有缺点 ( 小名称冲突问题是一个例外)。 与C++
一样,多重inheritance实现存在很大的缺点 。 这些包括效率考虑因素以及确定在某些情况下将执行哪些代码的语义难度。
实现Comparable的Polynomial类需要实现接口中声明的所有函数。
public class Polynomial implements Comparable { . . . boolean less(Object m){ . . . } boolean greater(Object m){ . . . } boolean lessEqual(Object m){ . . . } boolean greaterEqual(Object m){ . . . } Polynomial multiply(Polynomial P){ . . . } . . . }
类可以选择实现任意数量的接口。 实现接口的类必须为该接口的所有方法提供实体。 此外,我们希望抽象类可以选择实现接口的一部分,其余部分用于非抽象子类。
接口的用处远远超出了为其他程序员发布协议的范围。 任何函数都可以具有接口类型的参数。 实现接口的类中的任何对象都可以作为参数传递。
参考文献:
接口
接口
界面维基
接口方法没有像
public interface Flyable { public void fly(); }
因为界面本身不会做任何事情
接口是定义合同。
另一方面,界面定义了一个类可以做什么,而不是它是什么。 所以界面通常是关于动词的。
所以Flyable接口什么也没做,只是定义了植入的FlyableObjects将要飞的合同。
喜欢:
class Rocket implements Flyable { public void fly() { // do the stuffs. } }
接口
当然,我们也只能通过接口实现多重inheritance。
如果界面有身体,那么它会带回死亡的Daimond of Death问题。
考虑这个与主体接口的例子
interface A { void print(){ System.out.print("A") } } interface B { void print(){ System.out.print("B") } } interface C extends A, B { // now since A and B have bodies interfaces would have had choice to not to override the default behavior } public class C_Implementer implements C{ public static void main(String args[]){ C c = new C_Implementer(); c.print(); // gotcha!!!!! what should it print, A or B???? } }
您在问“为什么Java不支持多重inheritance实现?”
这在Java教程,状态的多重inheritance,实现和类型中讨论 ,但我想给出一个特定的实例多重inheritance问题的例子(以及最后的新语言特性解决方案)。
想象一下两个接口(在我们提出的允许接口方法体的Java版本中)定义了一个具有相同名称的方法。
public interface FaceOne { public void method() { System.out.println("FaceOne Version"); } } public interface FaceTwo { public void method() { System.out.println("FaceTwo Version"); } }
并且类实现两个接口,但不会覆盖该方法。
public class Inheriter implements FaceOne, FaceTwo { }
当我调用Inheriter.method()
,由于该类从其祖先inheritance了该方法,因此会出现问题:输出是否打印“FaceOne Version”或“FaceTwo Version”?
另外,如果类要覆盖该方法,但又想使用super
调用其祖先的版本,编译器将再次无法在该方法的版本之间进行选择。
这就是Java不支持多重inheritance实现的原因。
顺便说一句,我认为在语言中实现这一点的一种优雅方式如下:
继续强制实现类来覆盖其祖先接口的方法。 这解决了非重写方法的第一个问题。
然后,使用与访问内部类的封闭实例相似的表示法来访问具有super
的特定祖先接口。 然后,Inheriter类将有多个选项:
-
不要调用
super.method()
,而只使用新定义的实现。 -
使用
FaceOne.super.method()
使默认inheritance的实现输出“FaceOne Version”。 -
使用
FaceTwo.super.method()
使默认inheritance的实现输出“FaceTwo Version”。 -
使用以上组合:
一种实现可能是:
@Override public void method() { FaceOne.super.method(); FaceTwo.super.method(); System.out.println("Inheriter Version"); }
输出:
FaceOne版本
FaceTwo版本
inheritance人版本
编辑:根据这个问题,这显然是如何在Java 8中构建默认实现。