Java 隐藏接口的默认方法
考虑以下情况Java 隐藏接口的默认方法,java,java-8,default-method,Java,Java 8,Default Method,考虑以下情况 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) {
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
default方法的书,特别是关于
第二项:重新声明默认方法,使其抽象化
在上面的示例中,我有两个具有相同名称的默认方法的接口,当我实现这两个接口时,我只能实现Test
的printHello
,它指的是IFace2
我对此没有什么问题
IFace1
的printHello
方法?如果我不能,为什么李>
IFace1
的预期性质,因为它现在可能会被其他方法所掩盖引用中说,您可以在它的子界面中设置
默认
方法抽象
。比如说,
在这里,当我实现IFace2
时,我实际上无法达到IFace1
的default
方法,这正是我的情况
我怎样才能达到IFace1的printHello方法?如果不能,为什么
只能在使用实现IFace1
的类型的实例方法中执行此操作
IFace1.super.printHello(); // only if IFace1 declares a default implementation of the method
换句话说,您不能通过类型为IFace1
或Test
(或其他)的简单引用来实现。这将破坏封装
这种行为难道没有让我远离IFace1的预期性质吗
哪一个现在可能会被其他方法遮蔽
这里没有阴影。您已经重写了该方法,因此将调用被重写的方法
关于你的第三个问题,你没有扩展任何接口,所以我看不出相关性
如果你真的有
interface IFace2 extends IFace1 {
void printHello();
}
与
然后您将无法访问该方法的
IFace1
的default
实现。您永远不能跳过超级类型来访问继承层次结构中更高层次的实现。您似乎对默认方法的存在感到有点困惑。让我们暂时忘记IFace1.printHello()
是一种默认方法。因此,有一个明显的情况:Test
实现了两个接口,IFace1
和IFace2
,它们恰好有一个具有相同名称和签名的方法
Test
实现了该方法,因此实现了两个接口的方法。default
方法的新特性不会改变此逻辑。此外,语言设计者注意到添加default
方法不会影响现有代码的行为,因此如果类实现了该方法,那么default
方法的存在就变得无关紧要了
但是,如果您编写的代码知道存在default
方法,您可以调用它,如果它由直接超级接口声明或继承,即在代码中,您可以使用IFace1.super.printHello()
调用IFace1
的default
方法
这些规则与超类的规则没有太大区别。如果更改接口,使接口IFace2
扩展IFace1
,并且仍然将printHello()
声明为abstract
方法,则此abstract
方法会覆盖默认
方法,并且无法调用IFace1.super.printHello()
从测试中开始
如上所述,这些规则与普通实例方法没有太大区别。如果Test
声明了一个方法printHello()
,那么无论其声明的类型是Test
、IFace1
还是IFace2
,都只能通过引用Test
实例来调用该方法。只有Test
本身的实现方法才能执行super
调用
当涉及接口的可能多重继承时,主要的区别就开始发挥作用。如果您的类Test
没有实现方法printHello()
,它取决于两个接口的继承关系,会发生什么情况
- 如果
IFace2
扩展IFace1
,它的抽象方法将重新声明默认方法,因此会发生编译器错误,因为Test
必须实现抽象方法
- 如果
IFace2
没有扩展IFace1
,则存在两个具有相同名称和签名的可继承方法,因此Test
将不会继承默认方法,并且会发生编译器错误,因为Test
必须实现抽象方法
- 如果
IFace1
扩展IFace2
,Test
将继承default
方法。如果Test
没有实现IFace2
,它也将继承它,但这应该是一个惊喜
@TAsk:new Test()。printHello()
将始终调用Test
中声明的方法,无论您如何定义接口或Test
是否实现它们。@TAsk我不理解您的困惑。为什么您希望调用重写方法以外的任何东西?@TAsk您所说的有意义是什么意思?如果不在测试中重写它,代码将无法编译。
interface IFace2 extends IFace1 {
void printHello();
}
public class Test implements IFace2 {