隐藏接口的默认方法
Shadowing default method of an interface
考虑以下情况,
interface IFace1 {
default void printHello() {
System.out.println("IFace1");
}
}
interface IFace2 {
void printHello();
}
public class Test implements IFace1, IFace2 {
public static void main(String[] args) {
Test test = new Test();
test.printHello();
IFace1 iface1 = new Test();
iface1.printHello();
IFace2 iface2 = new Test();
iface2.printHello();
}
@Override
public void printHello() {
System.out.println("Test");
}
}
在上面的示例中,我得到以下输出,这是 相当 预期的。
Test
Test
Test
我一直在阅读 Java-8
默认方法,特别是 Extending Interfaces That Contain Default Methods
2nd bullet : Redeclare the default method, which makes it abstract.
在上面的示例中,我有两个具有相同名称的默认方法的接口,当我实现这两个接口时,我只能实现 Test
的 printHello
的实现,它指的是 IFace2
.
我对此没什么疑问,
- 我如何才能达到
IFace1
和的printHello
方法,如果我不能为什么 ?
- 这种行为不会让我远离
IFace1
的预期性质吗? 可能 现在被其他方法掩盖了?
Quote 说,您可以在其子界面中创建 default
方法 abstract
。 例如,
interface IFace2 extends IFace1 {
void printHello();
}
在这里,当我实现 IFace2
时,我实际上无法达到 IFace1
的 default
方法,这正是我的情况。
How can I reach to the printHello method of IFace1 and if I can't than why ?
您只能在实现 IFace1
和
的类型的实例方法中执行此操作
IFace1.super.printHello(); // only if IFace1 declares a default implementation of the method
换句话说,您不能通过 IFace1
或 Test
(或其他)类型的简单引用来实现。那会破坏封装。
Doesn't this behavior keep me away from the intended nature of IFace1
which is may be now shadowed by other method ?
这里没有阴影。您已覆盖该方法,因此将调用覆盖的方法。
关于你的第三个问题,你没有扩展任何接口,所以我看不出相关性。
如果你真的有
interface IFace2 extends IFace1 {
void printHello();
}
和
public class Test implements IFace2 {
那么您将无法访问 IFace1
的 default
方法实现。您永远不能跳过超类型来访问继承层次结构中更高层的实现。
看来您对 default
方法的存在有点困惑。所以让我们暂时忘记 IFace1.printHello()
是一个 default
方法。那么,就有一个明确的情况:Test
实现了IFace1
和IFace2
两个接口,恰好有同名同签名的方法
Test
实现了该方法,因此为两个接口都实现了该方法。 default
方法的新功能不会改变此逻辑的任何内容。此外,语言设计者注意添加 default
方法不会影响现有代码的行为,因此如果您的 class 实现了该方法,default
方法的存在就变得无关紧要了。
但是,如果您编写的代码知道 default
方法的存在,您可以调用它,如果它是由直接超级接口声明或继承的,即在您的代码中您可以使用 IFace1.super.printHello()
调用 IFace1
.
的 default
方法
规则与超级classes的规则没有太大区别。如果您更改接口,使接口 IFace2
扩展 IFace1
并且仍将 printHello()
声明为 abstract
方法,那么此 abstract
方法会覆盖 default
方法,您不能再从 Test
中调用 IFace1.super.printHello()
。
如前所述,这些规则与普通实例方法没有太大区别。如果 Test
声明了一个方法 printHello()
,那就是 只有 方法,您可以通过对 Test
实例的引用来调用该方法,而不管其声明的类型是否是 Test
、IFace1
或 IFace2
。只有 Test
本身的实现方法可以进行 super
次调用。
当涉及可能的接口多重继承时,主要区别就开始发挥作用。如果你的classTest
确实没有实现方法printHello()
,就看两个接口的继承关系了,会怎么样
- 如果
IFace2
扩展了 IFace1
,它的抽象方法重新声明了 default
方法,因此会出现编译器错误,因为 Test
必须实现 abstract
方法
- 如果
IFace2
不继承IFace1
,则有两个同名同签名的可继承方法不明确,因此Test
不会继承default
方法,并且发生编译器错误,因为 Test
必须实现 abstract
方法
- 如果
IFace1
扩展IFace2
,Test
将继承default
方法。如果 Test
没有实现 IFace2
,它也会继承它,但这应该令人惊讶……
考虑以下情况,
interface IFace1 {
default void printHello() {
System.out.println("IFace1");
}
}
interface IFace2 {
void printHello();
}
public class Test implements IFace1, IFace2 {
public static void main(String[] args) {
Test test = new Test();
test.printHello();
IFace1 iface1 = new Test();
iface1.printHello();
IFace2 iface2 = new Test();
iface2.printHello();
}
@Override
public void printHello() {
System.out.println("Test");
}
}
在上面的示例中,我得到以下输出,这是 相当 预期的。
Test
Test
Test
我一直在阅读 Java-8
默认方法,特别是 Extending Interfaces That Contain Default Methods
2nd bullet : Redeclare the default method, which makes it abstract.
在上面的示例中,我有两个具有相同名称的默认方法的接口,当我实现这两个接口时,我只能实现 Test
的 printHello
的实现,它指的是 IFace2
.
我对此没什么疑问,
- 我如何才能达到
IFace1
和的printHello
方法,如果我不能为什么 ? - 这种行为不会让我远离
IFace1
的预期性质吗? 可能 现在被其他方法掩盖了?
Quote 说,您可以在其子界面中创建 default
方法 abstract
。 例如,
interface IFace2 extends IFace1 {
void printHello();
}
在这里,当我实现 IFace2
时,我实际上无法达到 IFace1
的 default
方法,这正是我的情况。
How can I reach to the printHello method of IFace1 and if I can't than why ?
您只能在实现 IFace1
和
IFace1.super.printHello(); // only if IFace1 declares a default implementation of the method
换句话说,您不能通过 IFace1
或 Test
(或其他)类型的简单引用来实现。那会破坏封装。
Doesn't this behavior keep me away from the intended nature of IFace1 which is may be now shadowed by other method ?
这里没有阴影。您已覆盖该方法,因此将调用覆盖的方法。
关于你的第三个问题,你没有扩展任何接口,所以我看不出相关性。
如果你真的有
interface IFace2 extends IFace1 {
void printHello();
}
和
public class Test implements IFace2 {
那么您将无法访问 IFace1
的 default
方法实现。您永远不能跳过超类型来访问继承层次结构中更高层的实现。
看来您对 default
方法的存在有点困惑。所以让我们暂时忘记 IFace1.printHello()
是一个 default
方法。那么,就有一个明确的情况:Test
实现了IFace1
和IFace2
两个接口,恰好有同名同签名的方法
Test
实现了该方法,因此为两个接口都实现了该方法。 default
方法的新功能不会改变此逻辑的任何内容。此外,语言设计者注意添加 default
方法不会影响现有代码的行为,因此如果您的 class 实现了该方法,default
方法的存在就变得无关紧要了。
但是,如果您编写的代码知道 default
方法的存在,您可以调用它,如果它是由直接超级接口声明或继承的,即在您的代码中您可以使用 IFace1.super.printHello()
调用 IFace1
.
default
方法
规则与超级classes的规则没有太大区别。如果您更改接口,使接口 IFace2
扩展 IFace1
并且仍将 printHello()
声明为 abstract
方法,那么此 abstract
方法会覆盖 default
方法,您不能再从 Test
中调用 IFace1.super.printHello()
。
如前所述,这些规则与普通实例方法没有太大区别。如果 Test
声明了一个方法 printHello()
,那就是 只有 方法,您可以通过对 Test
实例的引用来调用该方法,而不管其声明的类型是否是 Test
、IFace1
或 IFace2
。只有 Test
本身的实现方法可以进行 super
次调用。
当涉及可能的接口多重继承时,主要区别就开始发挥作用。如果你的classTest
确实没有实现方法printHello()
,就看两个接口的继承关系了,会怎么样
- 如果
IFace2
扩展了IFace1
,它的抽象方法重新声明了default
方法,因此会出现编译器错误,因为Test
必须实现abstract
方法 - 如果
IFace2
不继承IFace1
,则有两个同名同签名的可继承方法不明确,因此Test
不会继承default
方法,并且发生编译器错误,因为Test
必须实现abstract
方法 - 如果
IFace1
扩展IFace2
,Test
将继承default
方法。如果Test
没有实现IFace2
,它也会继承它,但这应该令人惊讶……