Java 8 introduces the concept of default methods. Consider the following interface with a default method :
public interface IDefaultMethod {
public abstract void musImplementThisMethod();
public default void mayOrMayNotImplementThisMethod() {
System.out.println(" This method is optional for classes that implement this interface ");
}
}
And a class that implements this interface :
public class DefaultMethodImpl implements IDefaultMethod {
@Override
public void musImplementThisMethod() {
System.out.println("This method must be implementd ");
}
@Override
public void mayOrMayNotImplementThisMethod() {
// TODO Auto-generated method stub
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
}
}
I have a question about the readability of the following call in the mayOrMayNotImplementThisMethod
:
IDefaultMethod.super.mayOrMayNotImplementThisMethod();
I understand that the reason for explicitly specifying the interface name in the above call is to avoid confusion in case multiple interfaces implemented by the class have the same method. What I don't understand is the meaning of the super
keyword in this context. When we say IDefaultMethod.super
, what exactly are we referring to here? Wouldn't IDefaultMethod.mayOrMayNotImplementThisMethod() be more readable than IDefaultMethod.super.mayOrMayNotImplementThisMethod()? Removing the super keyword makes it more readable at the cost of distinguishing between a static or non static method call.
I will try to contribute to the discussion by following my own reasonings about this.
First, let's see how this work with simple Java classes:
class Barney {
void foo() { System.out.println("Barney says foo"); }
}
class Fred extends Barney {
@Override void foo() { super.foo(); }
}
In this case if we invoke the method foo
in a Fred
instance it will ask for the implementation of the foo
method in its super class and execute that one.
Evidently, none of these others would work:
@Override void foo() { foo(); } //means this.foo() so infinite recursion
@Override void foo() { Barney.foo(); } //means a static method
There is a third configuration that we could do:
class Barney {
void foo() { System.out.println("Barney says foo"); }
class Fred extends Barney {
@Override void foo() { Barney.this.foo(); }
}
}
In this case if we invoke foo
in a instance of Fred
, since this instance would have a bond with its enclosing instance, this invocation would invoke the foo
method in the enclosing instance of Barney
.
For instance
new Barney().new Fred().foo();
So, the use of Barney.this
here is used to navigate between instances in an inner/outer relation.
Now let's try to repeat the same ideas with interfaces.
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
}
interface Fred extends Barney {
@Override default void foo() { Barney.super.foo(); }
}
As far as I can tell, this is exactly the same thing as with classes, it is just that in this case since an interface can inherit from more than one interface we simply qualify the super
keyword with the name of the interface we are targeting in this case.
The meaning is the same, we want to invoke the "implementation" of the foo
method in the super interface explicitly named.
As with classes, the following would not work:
@Override default void foo() { super.foo(); } //can't be sure of which interface
@Override default void foo() { this.foo(); } //infinite recursion
@Override default void foo() { Barney.foo(); } //static method
@Override default void foo() { Barney.this.foo(); } //not an inner class relation
So, the logical choice here is Interface.super.method()
.
A question here would be whether we cab ever have a use case like Interface.this.method
when using interfaces.
Not really, because interfaces represent a static context, therefore there is never a concept like that of inner classes between interfaces. So this is never possible.
interface Barney {
default void foo() { System.out.println("Barney says foo"); }
interface Fred extends Barney {
@Override default void foo() { Barney.this.foo(); }
}
}
Basically, this is not possible because the code above does not mean that an instance of Fred
would need to exist within the context of an instance of Barney
. This is just a static inner interface and instances of it can exist independently of any instances of the parent interface.
So, that's why this would not be a good choice.
So, as you can see, after all this the use of super
kind of makes sense, or at least I hope I have explained myself well enough to convey that idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With