Clarification: My question is not about overriding vs overloading functions. It's about overriding methods in superclasses that use composition.
Lets say I have two classes, A
and B
. They're really useful together, so I make another class composed of the two, called AB
. The problem with this is that subclasses of AB
have difficulty overriding A/B
's methods. I'm looking for suggestions on how to mitigate the effect described below.
Example:
A
: Has a function that calls another one of its own functions. In this case, loopA(int num)
loops and performs a()
num times.
public class A {
public void loopA(int num){
for(int i = 0; i < num; i++){
a();
}
}
public void a(){
System.out.println("A");
}
}
B
: Just random functionality.
public class B {
public void b(){
System.out.println("B");
}
}
AB
: A combination of the two.
public class AB {
A a = new A();
B b = new B();
public void loopA(int num){
a.loopA(num);
}
public void a(){
a.a();
}
public void b(){
b.b();
}
}
ValidatedAB
: AB
that validates before performing a()
public class ValidatedAB extends AB{
@Override
public void a(){
System.out.println("Validate A!");
super.a();
}
}
Problem
My problem is that calling ValidatedAB.loopA(int num)
will NOT call the overridden a()
in ValidatedAB
, but the original A.a()
.
ValidatedAB vab = new ValidatedAB();
vab.loopA(2);
//Desired Output:
Validate A!
A
Validate A!
A
//Actual Output:
A
A
Possible Solutions
1. Copy/Paste or Refactor A and B into AB
A simple solution that gets rid of composition but results in a large AB
class, and is also code duplication if we keep A
, B
, and AB
.
2. Subclass A and B separately, and inject both into ValidatedAB.
public class ValidatedA extends A {
@Override
public void a(){
System.out.println("Validate A!");
super.a();
}
}
public class ValidatedAB extends AB{
public ValidatedAB(A a, B b){
this.a = a;
this.b = b;
}
}
ValidatedAB vab = new ValidatedAB(new ValidatedA(), new B());
vab.loopA(2);
This will cause a lot of classes to be made (my team members hate that). It also exposes the fact that AB
is a composition of A
and B
(not a terrible thing in this scenario considering AB
has the same interfaces, but otherwise would probably get some dirty looks). Finally, it still has the same overriding problem if ValidatedAB
is subclassed.
Conclusion
I'm hoping to find a clean, non-bulky, encapsulated way to achieve the effect I'm trying to get, but I know there are always trade offs. As a junior developer, any suggestions would be greatly appreciated. Thanks.