Using this simplified implementation of the library, using method()
instead of M()
:
interface IFC {
void method();
}
class A implements IFC {
public void method() {
System.out.println("method in A");
};
}
As akuzminykh mentions in their comment
You'd write a class that has M and a field for IFC. In M you'd do your stuff and then call M of IFC, where IFC can be A, B or C. So you'd wrap all instances of A, B and C in such a class, which will avoid extending A, B and C.
The advantage of this is that you only have to account for it when initializing your classes by wrapping them: IFC wrapIFC = new IFCWrapper(new A());
. Once that's done, you don't need to handle the variable wrapIFC
any differently than you would any variable initialized with new A()
:
class IFCWrapper implements IFC {
IFC ifc;
IFCWrapper(IFC ifc) {
this.ifc = ifc;
}
public void method() {
always();
ifc.method();
}
void always() {
System.out.println("wrapper method");
}
}
You could also create a separate independent (abstract?) class or interface, that you call instead of calling method()
passing in your instances. The downside is that you'll have to remember to call this every time you'd want to call method()
on your instance. I picked the option to pass in any extra stuff I want for this example using a Runnable
:
class IFCExt {
static Runnable defaultRun = () -> System.out.println("default extra");
static void method(Runnable toRun, IFC ifc) {
toRun.run();
ifc.method();
}
}
Example run of the two variants:
public class Test {
public static void main(String[] args) {
IFC wrapIFC = new IFCWrapper(new A());
wrapIFC.method();
System.out.println();
IFC myIFC = new A();
IFCExt.method(IFCExt.defaultRun, myIFC);
IFCExt.method(() -> System.out.println("anything extra"), myIFC); // anything you'd want
}
}
prints:
wrapper method
method in A
default extra
method in A
anything extra
method in A