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

发布于 2024-09-14 05:29:29 字数 192 浏览 5 评论 0原文

我听到(并在这个网站上读到)很多关于“偏好组合优于继承”。

但什么是组合呢?我从人:哺乳动物:动物的角度理解继承,但我在任何地方都看不到组合的定义......

I hear (and read on this site) a lot about "favour composition over inheritance".

But what is composition? I understand inheritance from the point of Person : Mammal : Animal, but I can't really see the definition of composition anywhere...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

留一抹残留的笑 2024-09-21 05:29:29

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

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

这种方法的优点是类型 MammalPerson 不必遵守其先前父级的接口。这可能是一件好事,因为有时对超类的更改可能会对子类产生严重影响。

他们仍然可以通过这些类的私有实例来访问这些类的属性和行为,如果他们想公开这些前超类的行为,他们可以简单地将它们包装在公共方法中。

我在组合与继承中找到了一个很好的链接,其中包含很好的示例。比较两种关联类的基本方法

Composition refers to combining simple types to make more complex ones. In your example, composition could be:

Animal:
    Skin animalSkin
    Organs animalOrgans


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

Person::Mammal:
    string firstName
    string lastName

If you wanted to go totally composition (and get rid of all inheritance) it would look like this:

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

The advantage to this approach is that the types Mammal and Person do not have to conform to the interface of their previous parent. This could be a good thing because sometimes a change to the superclass can have serious effects on the subclasses.

They still can have access to the properties and behaviours of these classes through their private instances of these classes, and if they want to expose these former-superclass behaviours, they can simply wrap them in a public method.

I found a good link with good examples in Composition versus Inheritance. A Comparative Look at Two Fundamental Ways to Relate Classes.

轻许诺言 2024-09-21 05:29:29

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

Composition is simply the parts that make up the whole. A car has wheels, an engine, and seats. Inheritance is a "is a " relationship. Composition is a "has a" relationship.

鸠魁 2024-09-21 05:29:29

可以通过三种方式为类赋予行为。您可以将该行为写入类中;您可以从具有所需行为的类继承;或者您可以将具有所需行为的类作为字段或成员变量合并到您的类中。最后两种代表代码重用的形式,最后一种 - 组合 - 通常是首选。它实际上并没有为您的类提供所需的行为 - 您仍然需要在现场调用该方法 - 但它对您的类设计施加了更少的限制,并且使代码更容易测试和调试。继承有其一席之地,但组合应该是首选。

There are three ways to give behavior to a class. You can write that behavior into the class; you can inherit from a class that has the desired behavior; or you can incorporate a class with the desired behavior into your class as a field, or member variable. The last two represent forms of code reuse, and the final one - composition - is generally preferred. It doesn't actually give your class the desired behavior - you still need to call the method on the field - but it puts fewer constraints on your class design and results in easier to test and easier to debug code. Inheritance has its place, but composition should be preferred.

猫弦 2024-09-21 05:29:29

考虑:

class Engine
{

}

class Automobile
{

}


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

组合 - 对象的功能由不同类的集合组成。实际上,这意味着持有一个指向另一个类的指针,该类的工作将被推迟。

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

至于为什么组合优于继承,请查看圆椭圆问题

Consider:

class Engine
{

}

class Automobile
{

}


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

Composition - Functionality of an object is made up of an aggregate of different classes. In practice, this means holding a pointer to another class to which work is deferred.

Inheritance - Functionality of an object is made up of its own functionality plus functionality from its parent classes.

As to why composition is preferred over inheritance, take a look at the Circle-ellipse problem.

累赘 2024-09-21 05:29:29

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

页面有一篇很好的文章解释了为什么人们说“更喜欢组合而不是继承”,并举了一些例子。

An example of composition is where you have an instance of a class within another class, instead of inheriting from it.

This page has a good article explaining why people say "favour composition over inheritance" with some examples of why.

篱下浅笙歌 2024-09-21 05:29:29

组合

仅仅意​​味着使用引用其他对象的实例变量。


For an illustration of how inheritance compares to composition in the code reuse department, consider this very simple example:


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应用程序时,它将打印出“Peeling is吸引人。”,因为Apple继承(重用)了Fruit的peel实现()。但是,如果在将来的某个时刻,您希望将 peel() 的返回值更改为 Peel 类型,则将破坏 Example1 的代码。即使Example1直接使用Apple并且从未明确提及Fruit,您对Fruit的更改也会破坏Example1的代码。
欲了解更多信息参考
看起来像这样:

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 提供了一种重用 Fruitpeel() 实现的替代方法。 Apple 可以保存对 Fruit 实例的引用并定义自己的 peel() 方法,而不是扩展 Fruit只需调用 Fruit 上的 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();
    }
}

更多信息ref

composition

simply mean using instance variables that are references to other objects.


For an illustration of how inheritance compares to composition in the code reuse department, consider this very simple example:


1- Code via inheritance

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

When you run the Example1 application, it will print out "Peeling is appealing.", because Apple inherits (reuses) Fruit's implementation of peel(). If at some point in the future, however, you wish to change the return value of peel() to type Peel, you will break the code for Example1. Your change to Fruit breaks Example1's code even though Example1 uses Apple directly and never explicitly mentions Fruit.
for more info ref
Here's what that would look like:

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- Code via composition
Composition provides an alternative way for Apple to reuse Fruit's implementation of peel(). Instead of extending Fruit, Apple can hold a reference to a Fruit instance and define its own peel() method that simply invokes peel() on the Fruit. Here's the code:

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

for more information ref

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文