Language agnostic 喜欢组合而不是继承?

Language agnostic 喜欢组合而不是继承?,language-agnostic,oop,inheritance,composition,aggregation,Language Agnostic,Oop,Inheritance,Composition,Aggregation,为什么更喜欢组合而不是继承?每种方法都有哪些权衡?什么时候应该选择继承而不是组合?将包容视为一种有关系的关系。汽车有发动机,人有名字等等 把继承看作是一种关系。汽车是交通工具,人是哺乳动物等等 我不相信这种方法。我直接从by,第6.3节中了解到。我听到的一条经验法则是,当继承是“A-A”关系时,应该使用继承,当它是“A-A”关系时,应该使用组合。尽管如此,我觉得您应该始终倾向于组合,因为它消除了很多复杂性。在Java或C#中,对象一旦实例化就不能更改其类型 因此,如果您的对象需要根据对象状态或条

为什么更喜欢组合而不是继承?每种方法都有哪些权衡?什么时候应该选择继承而不是组合?

将包容视为一种有关系的关系。汽车有发动机,人有名字等等

把继承看作是一种关系。汽车是交通工具,人是哺乳动物等等


我不相信这种方法。我直接从by,第6.3节中了解到。

我听到的一条经验法则是,当继承是“A-A”关系时,应该使用继承,当它是“A-A”关系时,应该使用组合。尽管如此,我觉得您应该始终倾向于组合,因为它消除了很多复杂性。

在Java或C#中,对象一旦实例化就不能更改其类型

因此,如果您的对象需要根据对象状态或条件显示为不同的对象或表现出不同的行为,请使用合成:参考和设计模式


如果对象需要具有相同的类型,则使用继承或实现接口。

继承非常强大,但您不能强制它(请参阅:the)。如果您确实不能完全确定真正的“is-a”子类型关系,那么最好使用组合。

另一个非常实用的原因是,选择组合而不是继承与您的域模型有关,并将其映射到关系数据库。很难将继承映射到SQL模型(最终会遇到各种各样的棘手问题,比如创建不经常使用的列、使用视图等)。一些ORML试图处理这个问题,但它总是很快变得复杂。构图可以很容易地通过两个表之间的外键关系来建模,但是继承更加困难。

除了有一个考虑之外,还必须考虑对象必须继承的“深度”。任何超过五到六级继承深度的内容都可能会导致意外的强制转换和装箱/拆箱问题,在这种情况下,合成对象可能是明智的选择。

更喜欢合成而不是继承,因为它更具可塑性/更容易在以后修改,但不要使用“始终合成”方法。通过组合,可以很容易地使用依赖项注入/设置器动态更改行为。继承更为严格,因为大多数语言不允许从多个类型派生。因此,一旦你从TypeA衍生出来,鹅或多或少都是熟的

我的上述酸性测试是:

  • TypeB是否希望公开TypeA的完整接口(所有公共方法都不少于),以便TypeB可以在需要TypeA的地方使用?表示继承

    • e、 塞斯纳双翼飞机将暴露飞机的完整界面,如果不是更多的话。因此,它适合从飞机上衍生出来
  • TypeB是否只希望TypeA暴露部分行为?表示需要合成。

    • e、 鸟可能只需要飞机的飞行行为。在这种情况下,将其提取为接口/类/两者并使其成为这两个类的成员是有意义的
更新:刚刚回到我的答案,现在看来,如果没有特别提到Barbara Liskov作为“我应该从这个类型继承吗?”测试的话,它是不完整的。

当你想“复制/公开基类”API时,你可以使用继承。当您只想“复制”功能时,请使用委派


其中一个例子是:您希望从列表中创建一个堆栈。堆栈只有弹出、推送和窥视。你不应该使用继承,因为你不想向后推、向前推、移除等等。这是堆栈中的一种功能。

简而言之,我同意“更喜欢合成而不是继承”,但对我来说,这听起来常常像是“更喜欢土豆而不是可口可乐”。有继承的地方,也有创作的地方。你们需要理解差异,然后这个问题就会消失。它对我来说真正的意义是“如果你打算使用继承——再想想,你可能需要组合”

当你想吃的时候,你应该更喜欢土豆而不是可口可乐,当你想喝的时候,你应该更喜欢可口可乐而不是土豆

创建子类应该不仅仅意味着调用超类方法的一种方便方式。当子类在结构上和功能上都是超类时,当它可以用作超类时,您应该使用继承,并且您将使用它。如果不是这样,那就不是继承,而是别的东西。合成是指对象由另一个对象组成,或与另一个对象有某种关系


所以对我来说,如果一个人不知道他是否需要继承或合成,真正的问题是他不知道他是想喝酒还是想吃饭。更多地思考你的问题领域,更好地理解它。

如果你理解其中的区别,解释起来就更容易了

程序代码 一个例子是不使用类的PHP(尤其是在PHP5之前)。所有逻辑都编码在一组函数中。您可以包含包含帮助函数等的其他文件,并通过在函数中传递数据来执行业务逻辑。随着应用程序的增长,这可能很难管理。PHP5试图通过提供更多面向对象的设计来解决这一问题

遗产 这鼓励使用类。继承是OO设计的三大原则之一(继承、多态、封装)

这是遗产在起作用。员工“是”个人或继承人。所有继承关系都是“is-a”关系。Employee还从Person(即Employee)隐藏了Title属性。Title将返回员工而不是此人的标题

作文 作文比继承更受欢迎。说实在的
class Person {
   String Title;
   String Name;
   Int Age
}

class Employee : Person {
   Int Salary;
   String Title;
}
class Person {
   String Title;
   String Name;
   Int Age;

   public Person(String title, String name, String age) {
      this.Title = title;
      this.Name = name;
      this.Age = age;
   }

}

class Employee {
   Int Salary;
   private Person person;

   public Employee(Person p, Int salary) {
       this.person = p;
       this.Salary = salary;
   }
}

Person johnny = new Person ("Mr.", "John", 25);
Employee john = new Employee (johnny, 50000);
class Manager : Person, Employee {
   ...
}
Class Manager {
   public string Title;
   public Manager(Person p, Employee e)
   {
      this.Title = e.Title;
   }
}
Class Aircraft extends Engine{
  var wings;
}
Class Aircraft {
  var wings;
  var engine;
}
class List {
  data = new Array();

  Integer size() {
    return data.length;
  }

  add(Integer anInteger) {
    data[data.length] = anInteger;
  }
}
class Set, inheriting from: List {
  add(Integer anInteger) {
     if (data.notContains(anInteger)) {
       super.add(anInteger);
     }
  }
}
class Vehicle{
     protected double getPrice(){
          // return price
     }
} 

class Car{
     Vehicle vehicle;
     protected double getPrice(){
          return vehicle.getPrice();
     }
}