Shadowing default method of an interface

那年仲夏 提交于 2019-11-30 20:33:28

It seems that you are a bit confused by the presence of a default method. So let’s forget for a moment that IFace1.printHello() is a default method. So then, there is a clear situation: Test implements two interfaces, IFace1 and IFace2, which happen to have a method with the same name and signature.

Test implements that method and therefore implements the method for both interfaces. The new feature of default methods does not change anything about this logic. Moreover, the language designers took care that adding a default method does not affect the behavior of existing code, so if your class implements the method, the presence of default methods becomes irrelevant.

However, if you write code that is aware of the presence of default methods, you may invoke it, if it is declared or inherited by a direct super interface, i.e. in your code you may use IFace1.super.printHello() to invoke the default method of IFace1.

The rules are not much different to the rules of super classes. If you change the interfaces so that interface IFace2 extends IFace1 and still declares printHello() as an abstract method, then this abstract method does override the default method and you can’t invoke IFace1.super.printHello() from within Test anymore.

As said, these rules are not much different to ordinary instance methods. If Test declares a method printHello(), that’s the only method that you can invoke by a reference to a Test instance, regardless whether its declared type is Test, IFace1 or IFace2. Only implementation methods of Test itself may do super invocations.


The main difference comes into play when the possible multiple inheritance of interfaces is involved. If your class Test does not implement the method printHello(), it depends on the inheritance relationship of the two interfaces, what will happen

  • If IFace2 extends IFace1, it’s abstract method redeclares the default method, hence a compiler error occurs, as Test must implement the abstract method
  • If IFace2 does not extend IFace1, there are ambiguously two inheritable methods with the same name and signature, therefore Test will not inherit the default method, and a compiler error occurs, as Test must implement the abstract method
  • If IFace1 extends IFace2, Test will inherit the default method. It will also inherit it if Test does not implement IFace2, but this should come at a surprise…

How can I reach to the printHello method of IFace1 and if I can't than why ?

You can only do so within an instance method of a type that implements IFace1 with

IFace1.super.printHello(); // only if IFace1 declares a default implementation of the method

In other words, you can't do it through a simple reference of type IFace1 or Test (or whatever). That would break encapsulation.

Doesn't this behavior keep me away from the intended nature of IFace1 which is may be now shadowed by other method ?

There's no shadowing going on here. You've overriden the method, so the overriden one gets invoked.

Concerning your 3rd question, you haven't extended any interfaces, so I don't see the relevance.

If you really did have

interface IFace2 extends IFace1 {
    void printHello();
}

with

public class Test implements IFace2 {

then you would not be able to access IFace1's default implementation of the method. You can never skip super types to access implementations higher up in the inheritance hierarchy.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!