简体   繁体   English

组成继承

[英]Inheritance with composition

I am designing a system, I have not yet implemented first I am just diagraming it and then will code it, I want to ask one simple question: 我正在设计一个系统,但我尚未实现,我只是对其进行图解,然后对其进行编码,我想问一个简单的问题:

What to do when we are using both inheritance and composition at the same time? 当我们同时使用继承和组合时该怎么办?

For example, in a hotel, there are 2 kinds of room standard room and Twin room let us say. 例如,在旅馆中,有两种房间标准间和双床间。 For this I can use inheritance concept and these 2 kinds of rooms will be derived class but i can also use composition and will make seperate class for standard and twin room, then will use this is my hotel class. 为此,我可以使用继承概念,这两种房间将是派生类,但是我也可以使用组合,将标准间和双床间设为单独的类,然后将其用作我的酒店类。

What should I do? 我该怎么办?

This question is kinda vague and there are many details missing, yet I'll share some ideas... 这个问题有点含糊,缺少许多细节,但我会分享一些想法...

First thing: while working on design of your application, what matters the most are the requirements . 第一件事:在设计应用程序时,最重要的是需求

You need to try to identify entities that will have some meaning in your system first. 您首先需要尝试识别将在您的系统中具有某些含义的实体。 Let's say you know that there will be Hotel and Room . 假设您知道会有HotelRoom Note, that this relation is a composition already, mainly because: 请注意,此关系已经是一个组合,主要是因为:

  • room can be part of only 1 hotel, it is not shared among multiple hotels 房间只能是1家酒店的一部分,不能在多家酒店之间共享
  • once the hotel is destroyed, so are all rooms in it 一旦酒店被摧毁,里面的所有房间也都被摧毁

in C++, composition usually means "by value", ie class Hotel could have Room room; 在C ++中,组合通常表示“按值”,即class Hotel可以有Room room; that would be an object with automatic storage duration with its lifetime tied to the lifetime of instance of Hotel , with multiple rooms you could just put them to the vector yielding the same relationship: 这将是一个具有自动存储持续时间的对象,其生命周期与Hotel实例的生命周期相关联,如果您拥有多个房间,则可以将它们放到矢量中,以产生相同的关系:

class Room { ... };

class Hotel {
public:
    std::vector<Room> rooms;
};

(By the way, an aggregation would be most likely represented by a pointer or reference). (顺便说一句,聚集很可能由指针或引用表示)。 This is another good example of composition: 这是组成的另一个很好的例子:

在此处输入图片说明

If you know that there will be different kinds of rooms, first questions should be: will these objects have different behaviour? 如果您知道会有各种房间,那么第一个问题应该是:这些物体的行为是否不同? will my system treat them in different way? 我的系统会以不同的方式对待他们吗? ...maybe you don't need to go for finer granularity than Room and everything that a concrete room will be specific with will be expressed with its attributes - size, number of beds, maybe dozens of boolean "has" flags ("has aircon", "has TV", "has microwave", ...), maybe all of its properties can be expressed with simple "type", values of which you would put into the enum . ...也许您不需要追求比Room更细的粒度,并且具体房间的所有内容都将通过其属性来表示-大小,床位数,也许数十个布尔型“ has”标志(“ has” aircon”,“有电视”,“有微波炉”,...),也许它的所有属性都可以用简单的“类型”表示,您可以将其值放入enum

I the case you site, I would have a room_type property on the room class, and I would set the type of the room_type property to an enumerated type with possible values of STANDARD and TWIN. 如果您在站点上,我将在room类上拥有一个room_type属性,并且将room_type属性的类型设置为枚举类型,并可能使用STANDARD和TWIN值。

As long as there are not significant behavioral differences depending upon this type field, I would keep it simple. 只要根据此类型字段没有明显的行为差异,我就将其保持简单。

If there are complicated behaviors, like predicting clean up based upon number of beds, changing pricing, and so on, I would use an abstract base class CRoom, and inherit CStdRoom and CTwinRoom from that, possibly setting a constant num_of_beds property in the class constructors. 如果存在复杂的行为,例如根据床位数预测清理,更改价格等,我将使用抽象基类CRoom,并从中继承CStdRoom和CTwinRoom,并可能在类构造函数中设置常量num_of_beds属性。

You shouldn't use language inheritance to model business requirement inheritance. 您不应该使用语言继承为业务需求继承建模。 It just makes it too hard to modify or extend the business model. 这只是使其很难修改或扩展业务模型。 Language inheritance is for implementing features of your model, not the model itself. 语言继承用于实现模型的功能,而不是模型本身。

Instead, derive all your objects from 'business object' or similar, to encapsulate common internal behaviour such as serialisation. 而是从“业务对象”或类似对象派生所有对象,以封装常见的内部行为,例如序列化。 Your classes can have types and you can use typeinfo, or you can use an explicit type field. 您的类可以具有类型,可以使用typeinfo,也可以使用显式类型字段。 Either way links between objects, whether inheritance-like or composition-like should be pointers (or index id fields) and collections (of pointers or index ids). 无论对象是继承还是合成,对象之间的两种链接都应该是指针(或索引ID字段)和集合(指针或索引ID的集合)。 [Your code snippet is fine, but pointers complicate memory management which integer ids avoid.] [您的代码段很好,但是指针使整数ID避免的内存管理复杂化。]

Complicated behaviours should belong to other classes such as the Pricing, Cleaning, etc. There are other patterns to use in setting the relationships between business objects and business actions, but again avoid crystallising them using language features. 复杂的行为应属于其他类别,例如定价,清洁等。在设置业务对象和业务动作之间的关系时,还可以使用其他模式,但也要避免使用语言功能使它们具体化。 You will regret it, if the system grows or changes even a bit. 如果系统有所增长或改变,您将后悔。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM