比继承更喜欢构图?

为什么喜欢构图而不是继承? 每种方法都有哪些折衷? 你应该什么时候选择继承而不是组合?


因为它比以后更容易/更容易修改,但不要使用组合总是方法,所以希望组合优于继承。 有了构图,使用依赖注入/设置器可以轻松改变行为。 继承比较严格,因为大多数语言不允许你从多个类型派生。 所以,一旦你从TypeA派生出来,鹅或多或少地被煮熟了。

我对以上的酸性测试是:

  • TypeB是否希望公开TypeA的完整接口(所有公共方法都不少于),以便可以在需要TypeA的情况下使用TypeB? 表示继承
  • 例如塞斯纳双翼飞机将暴露飞机的完整界面,如果不是更多的话。 所以这使它适合从飞机派生。

  • TypeB是否只需要TypeA暴露的部分/部分行为? 表示需要合成。
  • 例如,一只鸟可能只需要一架飞机的飞行行为。 在这种情况下,将它作为接口/类/两者提取出来并使其成为这两个类的成员是有意义的。

    更新:刚回到我的答案,现在看来,如果没有具体提及芭芭拉·利斯科夫的Liskov替换原则,它是不完整的,作为'我应该继承这种类型吗?'的测试。


    把遏制看成是一种关系。 一辆车“有一个”引擎,一个人“有一个”名字等。

    认为继承是一种关系。 汽车是“车辆”,“人”是“哺乳动物”等。

    我不赞同这种方法。 我直接从史蒂夫麦康奈尔第6.3版的Code Complete第二版中直接获悉。


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

    程序代码

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

    遗产

    这鼓励使用类。 继承是面向对象设计的三个原则之一(继承,多态,封装)。

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

    这是工作中的继承。 员工“是”人或继承人。 所有的继承关系都是“是一种”关系。 员工还会从Person中隐藏Title属性,这意味着Employee.Title将为Employee而非Person返回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);
    

    构图通常是“拥有”或“使用某种”关系。 这里Employee类有一个Person。 它不会从Person继承,而是将Person对象传递给它,这就是为什么它具有“Person”。

    继承构成

    现在说你想创建一个管理器类型,所以你最终得到:

    class Manager : Person, Employee {
       ...
    }
    

    这个例子可以正常工作,但是,如果Person和Employee都声明了Title怎么办? Manager.Title应该返回“运营经理”还是“Mr.”? 在构图下,这种模糊性得到更好的处理:

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

    管理器对象由员工和人员组成。 标题行为取自员工。 这种明确的组合消除了其他内容中的歧义,并且您会遇到更少的错误。

    链接地址: http://www.djcxy.com/p/9129.html

    上一篇: Prefer composition over inheritance?

    下一篇: AddRange to a Collection