当我们在一个类中实现一个接口时,我们需要确保该接口定义的所有方法都出现在类的源代码中。那么为什么这段代码容易编译呢?
interface A {
void f();
}
class X {
public void f() {}
}
class Y extends X implements A {
}
因为X
已经实现了f()
方法Y
extends X
,这使得它继承了该方法的实现。
对于这种情况,解决方法是方法签名。并且 class X
,即使没有实现 A 接口,也有一个具有正确签名的方法。所以实现类Y
也有那个方法。
X
我想说的是,只有在没有办法让类也实现接口(外部库、代码冻结、坏老板等)时才应该使用这样的构造——虽然有效——因为它让人有些头疼发生了什么...阅读代码的人必须导航到该类X
,并在那里找到f()
方法...
首先,我误读了这个问题,这些问题在X implements A
出现时也是有效的。
即使您明确指定了该X implements A
子句,也没关系 - 在这种情况下这是多余的。
如果X
是抽象的,并且Y
没有实现f()
,Y
将被迫实现该方法,除非Y
也被声明为抽象的。
如果某些接口方法没有在派生类中实现,但在基类中存在,则将使用基类中的实现。
interface A {
void f();
}
class X {
public void f() {}
}
编译器在这里检查 method f()
,如果它的定义没有写在同一个类中,那么它将在基类中查找定义。这是继承的基本属性
class Y extends X implements A {
}
您可以将其理解为f()
间接存在于课堂Y
上。
首先编译器会读取类Y
,然后它会转到接口,然后它会在类中A
搜索方法。如果它没有写在那里,那么它将在基类中搜索,即f()
Y
x
从哪里得到它必须在类的源代码中的声明?
一个类必须实现由已实现interface
或父 ( abstract
)定义的所有方法,class
否则必须声明abstract
。
所以当然 Y 类会编译。
java中的简单概念是子继承其父的属性,如果是这种情况则Y
已经f()
可用。这不是魔术。
尽管类X没有实现接口A,但它确实有一个恰好与接口方法签名匹配的公共方法。当类Y扩展类X时,它会继承该方法,编译器会将其视为接口方法的有效实现。