I have a two abstract
classes FlyingBird
and RunningBird
public abstract FlyingBird extends Bird implements IFlyingBird {}
public abstract RunningBird extends Bird implements IRunningBird {}
Now I want to have an another abstract class that is both IRunningBird
and IFlyingBird
public abstract FlyingRunningBird extends Bird implements IFlyingBird, IRunningBird {}
In this class I am duplicating all the code from FlyingBird
and RunningBird
Aggregation of dependent class is not possible as both classes are abstract
The issue is if any bug fix or modification that is done on either FlyingBird
or RunningBird
will not reflect in FlyingRunningBird
. I need to update the FlyingRunningBird
too.
Is there any we can avoid this code duplication in FlyingRunningBird
? or
Use FlyingBird
and RunningBird
in FlyingRunningBird
to avoid code duplication?
Java was designed with the problems of multiple inheritance in C++ in mind. So only single inheritance and multiple interfaces. At that time in C++ there could be ambiguity of a method that could belong to two parent classes.
To achieve your goal, the solution is to use delegating:
Using an other conventional naming:
public interface Flying {
void fly();
double getWingSpan();
}
public class FlyingImplementation {
public FlyingImplementation(Bird bird)
...
}
public interface Running {
void run();
double getRunningSpeed();
}
public class RunningImplementation {
public RunningImplementation(Bird bird) {}
...
}
public abstract FlyingRunningBird implements Flying, Running, Bird {
private final Flying birdFlying;
private final Running birdRunning;
protected FlyingRunningBird() {
birdFlying = new FlyingImplementation(this);
birdRunning = new RunningImplementation(this);
}
@Override
public void fly() {
birdFlying.fly();
}
@Override
void run() {
birdRunning.run();
}
...
}
The common things in Bird
, which also could have a base class. Flying
and Running
are capabilities, names adjectives, sole responsibility: flying resp. running.
Delegating to birdFlying
and birdRunning
makes the "multiple inheritance" explicit and is by no means less expressive.
I think there are two ways you can approach this:
default
methods in the corresponding interface
, given that you're using Java 8+ and those methods do not need to access fields (in which case you'll need to have some accessors in your interface or reconsider your design).FlyingRunningBird
could be provided with an instance of FlyingBird
and an instance of RunningBird
(at construction time), and it will simply delegate the method calls for each of the interfaces to the corresponding implementation.In your case, you may use Helper classes -> classes that do not fall anywhere in the hierarchy but have the common code to avoid duplicacy.
Otherwise, from the OO point of view -
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.