J. Bloch in his Effective Java written for Java 6
mentioned the following (Item 17):
If you feel that you must allow inheritance from such a class, one reasonable approach is to ensure that the class never invokes any of its overridable methods and to document this fact. In other words, eliminate the class’s self-use of overridable methods entirely.
Item 18:
If you use abstract classes to define types, you leave the programmer who wants to add functionality with no alternative but to use inheritance. The resulting classes are less powerful and more fragile than wrapper classes.
While interfaces are not permitted to contain method implementations, using interfaces to define types does not prevent you from providing implementation assistance to programmers.
Now in Java 8
with its default method's implementation (using the other methods in the interface) interfaces are dangerous for inheritance.
For instance:
public inteface MyInterface{
public void compute(Object o);
public default void computeAll(List<Object> oo){
for(Object o: oo)
compute(o); //self-use
}
}
So, according to J. Bloch, it may introduce some problems when we try to implement the interface, because:
Overriding the methods like this (similar to what J.Bloch provided):
public class MyInterfaceCounter implements MyInterface{
private int count = 0;
@Override
public void compute(Object o) {
count++;
}
@Override
public void computeAll(List<Object> oo){
count += oo.size(); //Damn!!
MyInterface.super.computeAll(oo);
}
}
The client access the interfaces's internals, i.e. they have to know about the default implementation.
What to do with it in Java 8? Are the rules from Effective Java apply still applicable?
Moreover, we can't declare the default method as final
(as we can do for classes, it would make the self-use not too dangerous for overriders).
Java does not have closures. if you then do something like pass f to a function, scope is the scope of where it was defined.
Interfaces Changes In Java 8. The Java 8 release introduces or allows us to have static and default methods in the interfaces. Using default methods in an interface, the developers can add more methods to the interfaces. This way they do not disturb or change the classes that implement the interface.
Default methods were introduced to provide backward compatibility for old interfaces so that they can have new methods without affecting existing code.
Closeable extends IOException whereas AutoCloseable extends Exception. Closeable interface is idempotent (calling close() method more than once does not have any side effects) whereas AutoCloseable does not provide this feature. AutoCloseable was specially introduced to work with try-with-resources statements.
Okay, take the answer from your previous question and look what we can apply here:
You could simply avoid self-use.
In this case you can't. While implementing that interface your only choice to rely on (if you want to give a default implementation) is the method compute
. You have to use it or not give an implementation at all.
You could make one of the methods involved final, so it can't be overridden.
That won't work in an interface as well.
You could make the class final, so it can't be extended.
That won't work in an interface.
You could describe the class's self-use patterns in its Javadoc comment (meeting the requirement of letting other people know).
That is the only choice left here. Either document it or don't give a default implementation. So yes, the basic idea of it still applies, however your choices are somewhat limited.
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