Oop 与面向对象设计相关的组合是什么?

Oop 与面向对象设计相关的组合是什么?,oop,design-patterns,language-agnostic,composition,Oop,Design Patterns,Language Agnostic,Composition,我听到(并在这个网站上读到)很多关于“重作文轻继承”的文章 但什么是合成?我从人:哺乳动物:动物的角度理解遗传,但我真的看不出堆肥的定义。。有人能告诉我吗?组成就是组成整体的部分。汽车有轮子、发动机和座椅。继承是一种“是”的关系。组合是一种“has a”关系。组合的一个例子是,在另一个类中有一个类的实例,而不是从它继承 佩奇有一篇很好的文章解释了为什么人们说“偏好组合而非继承”,并举例说明了原因。组合指的是将简单类型组合成更复杂的类型。在您的示例中,组合可以是: Animal: Skin

我听到(并在这个网站上读到)很多关于“重作文轻继承”的文章


但什么是合成?我从人:哺乳动物:动物的角度理解遗传,但我真的看不出堆肥的定义。。有人能告诉我吗?

组成就是组成整体的部分。汽车有轮子、发动机和座椅。继承是一种“是”的关系。组合是一种“has a”关系。

组合的一个例子是,在另一个类中有一个类的实例,而不是从它继承


佩奇有一篇很好的文章解释了为什么人们说“偏好组合而非继承”,并举例说明了原因。

组合指的是将简单类型组合成更复杂的类型。在您的示例中,组合可以是:

Animal:
    Skin animalSkin
    Organs animalOrgans


Mammal::Animal: 
    Hair/fur mammalFur
    warm-blooded-based_cirulation_system heartAndStuff

Person::Mammal: 
    string firstName
    string lastName
如果您想完全使用合成(并摆脱所有继承),它将如下所示:

Animal:
    Skin animalSkin
    Organs animalOrgans

Mammal:
    private Animal _animalRef
    Hair/fur mammalFur
    warm-blooded-based_cirulation_system heartAndStuff

Person:
    private Mammal _mammalRef
    string firstName
    string lastName
这种方法的优点是,类型
哺乳动物
不必符合其先前父代的界面。这可能是一件好事,因为有时对超类的更改会对子类产生严重影响。 他们仍然可以通过这些类的私有实例访问这些类的属性和行为,如果他们想公开这些以前的超类行为,他们可以简单地将它们封装在公共方法中


我在这里找到了一个很好的例子链接:

有三种方法可以为类提供行为。您可以将该行为写入类中;您可以从具有所需行为的类继承;或者可以将具有所需行为的类作为字段或成员变量合并到类中。最后两种形式代表代码重用,最后一种形式——组合——通常是首选。它实际上并没有为类提供所需的行为—您仍然需要在字段上调用该方法—但它对类设计的约束更少,从而更易于测试和调试代码。继承有它的地位,但组合应该是首选

class Engine
{

}

class Automobile
{

}


class Car extends Automobile // car "is a" automobile //inheritance here
{ 
 Engine engine; // car "has a" engine //composition here

}
组合-对象的功能由不同类的集合组成。在实践中,这意味着持有一个指向另一个工作被延迟到的类的指针

继承-对象的功能由其自身的功能加上其父类的功能组成


至于为什么组合比继承更受欢迎,请看一下。

组合

简单地说就是使用引用其他对象的实例变量。
为了说明继承如何与代码重用部门中的组成进行比较,请考虑这个非常简单的例子:


1-通过继承进行编码

    class Fruit {

    // Return int number of pieces of peel that
    // resulted from the peeling activity.
    public int peel() {

        System.out.println("Peeling is appealing.");
        return 1;
    }
}

class Apple extends Fruit {
}

class Example1 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}
当您运行
Example1应用程序时
,它会打印出“剥皮很吸引人”,因为Apple继承(重用)了Fruit对
peel()
的实现。但是,如果在将来的某个时候,您希望将
peel()
的返回值更改为键入peel,您将中断
Example1
的代码。您对水果的更改破坏了Example1的代码,即使Example1直接使用Apple,并且从未明确提到水果。 有关更多信息,请参阅 下面是它的样子:

class Peel {

    private int peelCount;

    public Peel(int peelCount) {
        this.peelCount = peelCount;
    }

    public int getPeelCount() {

        return peelCount;
    }
    //...
}

class Fruit {

    // Return a Peel object that
    // results from the peeling activity.
    public Peel peel() {

        System.out.println("Peeling is appealing.");
        return new Peel(1);
    }
}

// Apple still compiles and works fine
class Apple extends Fruit {
}

// This old implementation of Example1
// is broken and won't compile.
class Example1 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}
2-通过合成编码 组合为
Apple
重用
Fruit的
实现
peel()
提供了一种替代方法。与扩展
Fruit
不同,
Apple
可以保存对
Fruit
实例的引用,并定义自己的
peel()
方法,该方法只需调用水果上的
peel()
。代码如下:

class Fruit {

    // Return int number of pieces of peel that
    // resulted from the peeling activity.
    public int peel() {

        System.out.println("Peeling is appealing.");
        return 1;
    }
}

class Apple {

    private Fruit fruit = new Fruit();

    public int peel() {
        return fruit.peel();
    }
}

class Example2 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}

有关更多信息

和聚合是一个。。。关系。聚合可以是简单的组合,或者如果它是类似事物的集合(例如,汽车上的车轮),则可以将其视为集合。一辆汽车可以有四个单独的车轮,它们是唯一标识的,也可以有一组车轮。这取决于使用情况。如果使用一个集合类,那么集合本身就是一个聚合。所以我可以这样说:“组合是当我在
类B
中创建
类a
的对象时(而不是从
类a
中对
类B
进行子类化)。”哦。好的,收到了,稍后再回答。是的,我可以这么说。不是一个类[C2]在另一个类[C1]中的实例,而是一个类在另一个类的实例中的实例。前者可能被误解为在定义C1时实例化了C2,这不应该是常见的。