In java 8 I have something like this:
package test;
public class SimpleFuncInterfaceTest {
public static void carryOutWork(AFunctionalInterface sfi){
sfi.doWork();
}
public static void main(String[] args) {
carryOutWork(() -> System.out.println("Do work in lambda exp impl..."));
AImplementor implementsA = new AImplementor();
//carryOutWork(() -> implementsA.doWork());
BImplementor implementsB = new BImplementor();
carryOutWork(() -> implementsB.doWork());
}
}
@FunctionalInterface
interface AFunctionalInterface {
public void doWork();
default public void doSomeWork(){
System.out.println("FOO");
}
}
@FunctionalInterface
interface BFunctionalInterface extends AFunctionalInterface {
@Override
default public void doSomeWork(){
System.out.println("BAR");//Unreachable in same object?
}
}
class AImplementor implements AFunctionalInterface {
@Override
public void doWork() {
doSomeWork();
}
}
class BImplementor extends AImplementor implements BFunctionalInterface {
public void doSomeWork(){
super.doSomeWork();
new BFunctionalInterface(){
@Override
public void doWork() {
}}.doSomeWork();
System.out.println("WUK WUK");
}
@Override
public void doWork() {
doSomeWork();
}
}
Is there a way to call the default functional interface behavior from implementsB without having to create an anonymous inner class and invoking that?
That has a side effect (calling implementsA's method 2 times), what is desired is a call to the parent's implementation, and then have the childs implementation be able to call the child's default implementation, along with some specialization if needed. As you can see calling the parent's implementation is dead easy, but I don't see a way to avoid re-writing the default implementation unless I add a layer of indirection to the class that implements the child interface, and no way to enforce that.
For instance if A unlocked or provided access to a resource say a database, and B unlocks a second resource (another database), I see no way to make code unlock A and then B enforcing this contract through the use of Functional Interfaces, requiring that A and B be called. One level deep you can do it, but N levels deep looks like it's not possible.
I intended to use lambdas to avoid making expensive calls but to enforce a semantic order of operations on users of my library.
This question is not quite the same as "Explicitly calling a default method in Java", as this question is about interfaces N levels deep, not just calling a parent interfaces default method.
You can invoke an inherited interface default
method using InterfaceName.super
. The rules are the same as for other super
method invocations: You can invoke the inherited method that you have overridden, but you can’t directly invoke the method which the inherited method might have overridden. E.g.
interface A
{
void foo();
default void toOverride() {
System.out.println("A");
}
}
interface B extends A
{
default void toOverride() {
A.super.toOverride();
System.out.println("B");
}
}
interface C extends B
{
default void toOverride() {
A.super.toOverride();// does not work
B.super.toOverride();
System.out.println("B");
}
}
class D implements B
{
public void toOverride() {
}
public void foo() {
D.this.toOverride();
B.super.toOverride();
A.super.toOverride(); // does not work!
}
}
But if each overriding method invokes its super method you have a chain of invocations. However, keep in mind that we are talking about interfaces. An implementation can always override a default method without invoking super
at all.