子类继承超类并添加属性
Subclass inherit superclass and add attributes
我有两个 class 看起来像这样
public class Animal {
public Leg leg;
}
public class Leg {
public Toe toe;
}
现在,我想要一个名为 Dog 的新 class 来扩展 class 动物,我想在 class 腿上添加毛发。如何扩展 class 使其工作?
假设您有一个 class A,并且您想要扩展 class A 的 class B,
Vois l'example suivante :
class A {
String a = "Hello world";
}
class B extends A {
void m () {
System.out.println (a);
}
}
Class B 将有权访问 class A 的所有属性。
只需创建您的 class 狗并使其扩展 Animal class:
public class Animal {
public Leg leg;
}
public class Dog extends Animal {
// dog have also leg from superclass
//add dog attributes here
}
与评论中的建议相反,这个问题不应该通过继承来解决。是的,即使实现一个接口也被认为是“软”继承,如果不对现有代码进行不必要的、“危险的”修改,就无法工作。 class 不应仅仅为了访问另一个 class 中包含的某些依赖项而扩展另一个。我知道这听起来很混乱。我想分享这个 Stack Overflow 答案,我在其中详细解释和说明了 Dependency Injection 的概念;这就是你解决这个问题所需要的。
在您的示例中,Animal
class 拥有一个不包含“头发”的属性 Leg
。随之而来的是一个新的 class Dog
,它需要一种包含“头发”而不是“脚趾”的不同类型的 Leg
。因此,这是对继承的错误使用。您需要做的是将“hairy-leg”行为注入到已经存在的 Animal
class 中,而不是创建一个新的 class 来展示不同的行为。例如:
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();
请注意,此方法无需不必要的继承链即可实现相同的目标。这种方法的其他好处:
- 遵守 Open/Close 原则:正确完成依赖注入后,无需修改现有功能即可扩展代码的功能。在 OP 的示例中,
Dog
class 的要求需要修改 Leg
class 以允许向其添加“头发”。这可能会影响现有的 Animal
class,这可能是不可取的。此更改需要对 Animal
进行更多测试,以确保更改不会干扰任何现有功能(仅举出此更改的一个负面方面)。
- 接口编码:使
Behavior
成为一个接口,允许代码无缝地采用新行为。在链接示例中,我提到了像 Apex Legends 和 Skyrim 这样的游戏如何具有“皮肤”的概念,您可以在其中动态地为角色添加属性。虽然我不确定这是如何实现的,但这似乎是通过一个通用界面完成的,该界面使用“策略”通过扩展“皮肤”而不是创建具有不同属性的新角色来将覆盖应用到角色。
理论上,您可以将一组行为映射到 Animal
class,以便为每个实例注入不同类型的行为。例如:进食行为、行走行为、声音行为、睡眠行为等
总而言之,这就是为什么你们中的一些人听到了以下表达或想法:更喜欢组合而不是继承.
我有两个 class 看起来像这样
public class Animal {
public Leg leg;
}
public class Leg {
public Toe toe;
}
现在,我想要一个名为 Dog 的新 class 来扩展 class 动物,我想在 class 腿上添加毛发。如何扩展 class 使其工作?
假设您有一个 class A,并且您想要扩展 class A 的 class B, Vois l'example suivante :
class A {
String a = "Hello world";
}
class B extends A {
void m () {
System.out.println (a);
}
}
Class B 将有权访问 class A 的所有属性。
只需创建您的 class 狗并使其扩展 Animal class:
public class Animal {
public Leg leg;
}
public class Dog extends Animal {
// dog have also leg from superclass
//add dog attributes here
}
与评论中的建议相反,这个问题不应该通过继承来解决。是的,即使实现一个接口也被认为是“软”继承,如果不对现有代码进行不必要的、“危险的”修改,就无法工作。 class 不应仅仅为了访问另一个 class 中包含的某些依赖项而扩展另一个。我知道这听起来很混乱。我想分享这个 Stack Overflow 答案,我在其中详细解释和说明了 Dependency Injection 的概念;这就是你解决这个问题所需要的。
在您的示例中,Animal
class 拥有一个不包含“头发”的属性 Leg
。随之而来的是一个新的 class Dog
,它需要一种包含“头发”而不是“脚趾”的不同类型的 Leg
。因此,这是对继承的错误使用。您需要做的是将“hairy-leg”行为注入到已经存在的 Animal
class 中,而不是创建一个新的 class 来展示不同的行为。例如:
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();
请注意,此方法无需不必要的继承链即可实现相同的目标。这种方法的其他好处:
- 遵守 Open/Close 原则:正确完成依赖注入后,无需修改现有功能即可扩展代码的功能。在 OP 的示例中,
Dog
class 的要求需要修改Leg
class 以允许向其添加“头发”。这可能会影响现有的Animal
class,这可能是不可取的。此更改需要对Animal
进行更多测试,以确保更改不会干扰任何现有功能(仅举出此更改的一个负面方面)。 - 接口编码:使
Behavior
成为一个接口,允许代码无缝地采用新行为。在链接示例中,我提到了像 Apex Legends 和 Skyrim 这样的游戏如何具有“皮肤”的概念,您可以在其中动态地为角色添加属性。虽然我不确定这是如何实现的,但这似乎是通过一个通用界面完成的,该界面使用“策略”通过扩展“皮肤”而不是创建具有不同属性的新角色来将覆盖应用到角色。
理论上,您可以将一组行为映射到 Animal
class,以便为每个实例注入不同类型的行为。例如:进食行为、行走行为、声音行为、睡眠行为等
总而言之,这就是为什么你们中的一些人听到了以下表达或想法:更喜欢组合而不是继承.