协慌网

登录 贡献 社区

喜欢构成而不是继承?

为什么喜欢构图而不是继承呢?每种方法都有哪些权衡取舍?什么时候应该选择继承而不是作文?

答案

首选组合而不是继承,因为它更具延展性 / 易于修改,但不使用 compose-always 方法。通过组合,可以使用依赖注入 / 设置器轻松更改行为。继承更加严格,因为大多数语言不允许您从多个类型派生。因此,一旦你从 TypeA 派生,鹅就会或多或少地煮熟。

我对上述的酸测试是:

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

例如,塞斯纳双翼飞机将暴露飞机的完整界面,如果不是更多。因此,它适合从飞机派生。

  • TypeB 是否只想要 TypeA 公开的部分 / 部分行为?表示需要合成。

例如,鸟可能只需要飞机的飞行行为。在这种情况下,将其作为接口 / 类 / 两者提取出来并使其成为两个类的成员是有意义的。

更新:刚回到我的答案,现在看来,如果不特别提及芭芭拉利斯科夫的利斯科夫替代原则作为 “我是否应该继承这种类型?” 的测试,它似乎是不完整的。

将遏制视为一种关系。汽车 “有一个” 引擎,一个人 “有一个” 的名字等。

想继承的作为是有关系的。汽车 “是” 汽车,人是 “哺乳动物” 等。

我不相信这种方法。我直接从Steve McConnell第二版 Code Code 中直接看到了第 6.3 节

如果您了解其中的差异,则更容易解释。

程序代码

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

遗产

这鼓励使用课程。继承是 OO 设计的三个原则之一(继承,多态,封装)。

class Person {
   String Title;
   String Name;
   Int Age
}

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

这是工作中的继承。员工 “是” 人或继承人。所有继承关系都是 “is-a” 关系。 Employee 还会从 Person 隐藏 Title 属性,这意味着 Employee.Title 将返回 Employee 的 Title 而不是 Person。

组成

组合比继承更受青睐。简单地说,你会有:

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);

组合通常 “具有” 或 “使用” 关系。这里 Employee 类有一个 Person。它不会从 Person 继承,而是将 Person 对象传递给它,这就是它“拥有”Person 的原因。

继承的组合

现在假设您要创建一个 Manager 类型,最终得到:

class Manager : Person, Employee {
   ...
}

这个例子可以正常工作,但是,如果 Person 和 Employee 都声明了Title ? Manager.Title 应该返回 “运营经理” 还是 “先生”?在构图下,这种歧义可以更好地处理:

Class Manager {
   public string Title;
   public Manager(Person p, Employee e)
   {
      this.Title = e.Title;
   }
}

Manager 对象由 Employee 和 Person 组成。标题行为取自员工。这种明确的组合消除了其他事物的歧义,你会遇到更少的错误。