我有兩個看起來像這樣的課程
public class Animal {
public Leg leg;
}
public class Leg {
public Toe toe;
}
現在,我想要一個名為 Dog 的新類來擴展類動物,我想在類腿上添加頭發。如何擴展類以使其作業?
uj5u.com熱心網友回復:
想象一下,你有一個 A 類,并且你想擴展 A 類的 B 類,Vois l'example suivante:
class A {
String a = "Hello world";
}
class B extends A {
void m () {
System.out.println (a);
}
}
B 類將有權訪問 A 類的所有屬性。
uj5u.com熱心網友回復:
只需創建您的類 dog 并使其擴展 Animal 類:
public class Animal {
public Leg leg;
}
public class Dog extends Animal {
// dog have also leg from superclass
//add dog attributes here
}
uj5u.com熱心網友回復:
與評論中的建議相反,這個問題不應該通過繼承來解決。是的,即使實作一個介面也被認為是“軟”繼承,如果不對現有代碼進行不必要的“危險”修改,就無法作業。一個類不應僅僅為了訪問另一個類中包含的某些依賴項而擴展另一個類。我知道這聽起來令人困惑。我想分享這個 Stack Overflow 答案,我在其中詳細解釋和說明了Dependency Injection的概念;這是您解決此問題所需要的。
在您的示例中,Animal該類擁有一個Leg不包含“頭發”的屬性。隨之而來的是一個新的類Dog,它需要一種Leg包含“頭發”而不是“腳趾”的不同型別。因此,這是對繼承的錯誤使用。相反,您需要做的是將“毛腿”行為注入到已經存在的Animal類中,而不是僅僅為了表現出不同的行為而創建一個新類。例如:
public class Animal {
Behavior behavior;
public void addBehavior(Behavior behavior) {
this.behavior = behavior;
}
public void displayBehavior() {
behavior.wiggle();
}
}
您可以創建一個可以注入特定動物實體的整個“行為”系列。對于這個例子,我將只創建兩個行為。
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");
}
}
然后,您只需將所需的行為“注入”到每個實體。
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
Dogclass would have needed modifying theLegclass to allow adding "hair" to it. This could impact the existingAnimalclass, which could be undesirable. This change would require more testing ofAnimalto ensure the change would not interfere with any existing functions (to name one negative aspect of this change). - Coding to interfaces: Making
Behavioran 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.
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/446638.html
