I have two classes that looks like this
public class Animal {
public Leg leg;
}
public class Leg {
public Toe toe;
}
Now, I would like to have a new class called Dog to extend class animal and I would like to add Hair on the class Leg. How to extend the class to make it work?
CodePudding user response:
Imagine that you have a class A and you want to extend a class B of class A, Vois l'exemple suivante :
class A {
String a = "Hello world";
}
class B extends A {
void m () {
System.out.println (a);
}
}
Class B will have access to all the attributes of class A.
CodePudding user response:
Just create your class dog and make it extends the Animal class:
public class Animal {
public Leg leg;
}
public class Dog extends Animal {
// dog have also leg from superclass
//add dog attributes here
}
CodePudding user response:
Contrary to the suggestion in the comments, this problem should not be solved through inheritance. Yes, even implementing an interface is consider "soft" inheritance and will not work without incurring in unnecessary, "dangerous" modifications to existing code. A class should not extend another simply to gain access to some a dependency contained in another class. I know that it sounds confusing. I would like to share this Stack Overflow answer where I explain and illustrate in detail the concept of Dependency Injection; which is what you need to solve this problem.
In your example, the Animal
class possesses an attribute Leg
that doesn't contain "hair". Along comes a new class Dog
that needs a different kind of Leg
that contains "hair" instead of "toes". Therefore, this is an incorrect use of inheritance. What you need to do instead is inject the "hairy-leg" behavior to the already existing Animal
class rather than create a new class only to exhibit a different behavior. For example:
public class Animal {
Behavior behavior;
public void addBehavior(Behavior behavior) {
this.behavior = behavior;
}
public void displayBehavior() {
behavior.wiggle();
}
}
You could create an entire family of "behaviors" that could be injected to a particular animal instance. For this example, I will create only two behaviors.
public interface Behavior {
void wiggle();
}
public class HairyLegBehavior implements Behavior {
@Override
public void wiggle() {
System.out.println("The wind is wiggling the hair on my legs");
}
}
public class ToeBehavior implements Behavior {
@Override
public void wiggle() {
System.out.println("I'm wiggling my toes");
}
}
Then, you simply "inject" the desired behavior to each instance.
Animal dog = new Animal();
Animal man = new Animal();
dog.addBehavior(new HairyLegBehavior());
man.addBehavior(new ToeBehavior());
dog.displayBehavior();
man.displayBehavior();
Notice that this approach accomplishes the same goal without the need of unnecessary inheritance chains. Other benefits of this approach:
- Observes the Open/Close principle: Dependency Injection when done properly, extends the capabilities of your code without the need to modify existing capabilities. In the OP's example, the requirement of the
Dog
class would have needed modifying theLeg
class to allow adding "hair" to it. This could impact the existingAnimal
class, which could be undesirable. This change would require more testing ofAnimal
to ensure the change would not interfere with any existing functions (to name one negative aspect of this change). - Coding to interfaces: Making
Behavior
an interface, allows the code to adopt new behavior seamlessly. In the linked example, I mentioned how games like Apex Legends and Skyrim have this concept of "skins", where you can add attributes to characters on the fly. Although I do not know for certain how this was implemented, it seems this is done thru a common interface using a "Strategy" for applying overlays to the characters by EXPANDING the "skins" rather than creating new characters with different attributes.
In theory, you could have a set of behaviors of a mapping of behaviors to the Animal
class to inject each instance with different types of behaviors. For example: eating behavior, walking behavior, sound behavior, sleep behavior, etc.
In conclusion, this is why some of you have heard the following expression or idea: Prefer composition over inheritance.