Java 子类能否从与接口无关的父类继承接口实现
这是一种古怪的情况。考虑这个例子:Java 子类能否从与接口无关的父类继承接口实现,java,polymorphism,Java,Polymorphism,这是一种古怪的情况。考虑这个例子: interface I { void foo(); } class B { public void foo() {} } class C extends B implements I {} 使用我的编译器(Linux中的OpenJDK),它可以编译并执行以下工作: I c = new C(); c.foo(); 为什么??它是有意的,并且有语言标准的支持吗?运行时如何知道先从I向下到C,然后从C向上到B?虽然在B实现I的情况下这一点很清
interface I {
void foo();
}
class B {
public void foo() {}
}
class C extends B implements I {}
使用我的编译器(Linux中的OpenJDK),它可以编译并执行以下工作:
I c = new C();
c.foo();
为什么??它是有意的,并且有语言标准的支持吗?运行时如何知道先从I
向下到C
,然后从C
向上到B
?虽然在B实现I
的情况下这一点很清楚,但考虑到B
与I
无关,这似乎是违反直觉的,它并不像您所想的那样“遵循”C
从B
继承所有非私有方法,C
可以用这些方法做任何事情;重写它们,使用它们实现接口(如果方法是public
),调用它们,等等
因此,方法
foo
是C
的方法,即使它是从B
继承而来的。一个类可以通过接口
公开它的任何公共方法。首先要注意的是扩展B和实现I的共同效果。java中的常见效果或明显结果是,您只能有一个具有特定名称、数据类型和参数的方法(类型相同,数量相同)
任何具有相同名称和不同参数数的方法都属于方法重载。但是在您的例子中,非常简单的是,您需要在一个具体的子类中实现和定义Abstract方法foo()
重新定义超类中的每个方法不是强制性的,但在实现接口时,它成为强制性的。因此Java认为类C
中的方法foo()
是从接口I
继承的方法。否则,您将看到一个错误,要求您重新定义从接口继承的方法foo()
不知不觉,当你考虑超类<代码> B/COD>时,这也成为方法重写的一个例子。由于
C
中的foo()
方法具有与B
和I
中相同的声明类型(它应该根据标准、规则和实现接口的规则进行声明),因此它很容易满足接口并重写B
中的方法
在您的例子中,您还重写了类B
中的方法foo()
因此,一个条件以及一个补充提议(压倒一切)正在得到满足
最后,class C
只有一个foo()
方法,它覆盖了B
中的方法,并且满足实现接口I
的条件
例如:
将方法foo()
定义为(在C
中):
在C
中创建2个对象,如下所示:
B b=new C();
C c=new C();
调用foo()
:
输出:两次打印Hello
结论:C
中的foo()
满足了接口(未发现错误),并且覆盖了B
中的foo()
方法。在您提到的C
示例中,是类C
的实例。因此,它需要有自己的方法foo()
现在,C已经从B
和foo()
获得了所有公共(和默认?)方法,由于B
,恰好是(技术上)存在的方法。因此,放置在C
上的接口有自己的foo()
方法的要求通过B
sfoo()
实现
我不认为从I到C的向下和从C到B的向上是相关的,就像你提到的那样
编辑:
所有证据都表明编译器手头有一个已实现函数的列表,这些函数都位于给定类中,并且是从父类扩展而来的“虚拟”函数
因此,如果前面提到的类正在实现某些接口,则扩展函数和类自己的函数都会与需要实现的函数(因为接口)进行比较。当您编写时,类C扩展B实现I
将从以下位置发生:
类C从其直接超类继承超类的所有具体方法m(静态和实例),对于这些方法,以下所有条件均为真:
- m是C的直接超类的一个成员
- m是公共的、受保护的,或者在与C相同的包中声明了包访问权
- C中声明的任何方法的签名都不是m签名的子签名(§8.4.2)
类C从其直接超类和直接超接口继承所有抽象和默认(§9.4)方法m,对于这些方法,以下所有条件均成立:
- m是C的直接超类或直接超接口D的成员
- m是公共的、受保护的,或者在与C相同的包中声明了包访问权
- C中声明的任何方法的签名都不是m签名的子签名(§8.4.2)
- C从其直接超类继承的具体方法没有签名是m签名的子签名
- 不存在作为直接超类成员的方法m'或C的直接超接口D'(m不同于m',D不同于D'),因此m'来自D'重写方法m的声明
所以它继承了接口I
的抽象方法和类B
的具有相同签名的具体方法。你是说接口I
@DebosmitRay谢谢..更正了它。正确吗
B b=new C();
C c=new C();
b.foo();
c.foo();