继承与组合的区别

继承与组合的区别

继承

若在逻辑上B是一种A(is a kind of),则允许B继承A的功能,它们之间就是is-A的关系。如男人(Man)是人(Human)的一种,女人(Woman)是人(Human)的一种。那么类Man可以从类Human派生,类Woman也可以从类Human派生。示例程序如下:

class Human
{
    ...
};
class Man : public Human
{
    ...
};
class Woman : public Human
{
	...  
};

在UML中,继承关系被称为泛化(Generalization)。类Man和类Woman与类Human的UML关系图可描述如下:

在这里插入图片描述

继承在逻辑上看起来比较简单,但在实际应用上可能遭遇意外。比如在面向对象中,著名的“鸵鸟不是鸟”和“圆不是椭圆”的问题。这样的问题说明了程序设计和现实世界存在逻辑差异。从生物学的角度,鸵鸟(Ostrich)是鸟(bird)的一种,既然是is-A的关系,类COstrich应该可以从类CBird派生。但是鸵鸟不会飞,但从CBird那里继承了接口函数fly,如下所示:

class CBird
{
public:
    virtual void fly() {}
};

class COstrich
{
public:
    ...
};

“圆不是椭圆“同样存在类似的问题,圆从椭圆类继承了无用的长短轴数据成员,所以更加严格的继承应该是:若在逻辑上B是A的一种,并且A的所有功能和属性对B都有意义,则允许B继承A的所有功能和属性。

类继承允许我们根据自己的实现来覆盖重写父类的实现细节,父类的实现对于子类是可见的,所以我们一般称之为白盒复用。继承易于修改或扩展那些被复用的实现,但是这种白盒复用却容易破坏封装性。因为这会将父类的实现细节暴露给子类。

组合

若在逻辑上A是B的”一部分“(a part of),则不允许B继承A的功能,而是要用A和其他东西组合出来B,它们之间就是 Has-A关系。例如眼(Eye),鼻(nose),口(mouth),耳(ear)是头(head)的一部分,所以类Head应该由Eye,Nose,Mouth,Ear组合而成,而不是派生而成。

class Eye
{
public:
    void Look(void);
};
class Nose
{
public:
    void Smell(void);
};
class Mouth
{
  	void Eat(void);  
};
class Ear
{
public:
    void Listen(void);
};
class Head
{
public:
    void Look(void) { m_eye.Look(); }
    void Smell(void) { m_nose.Smell(); }
    void Eat(void) { m_mouth.Eat(); }
    void Listen(void) { m_ear.Listen(); }
private:
    Eye m_eye;
    Nose m_nose;
    Mouth m_mouth;
    Ear m_ear;
};

如果允许Head从Eye,Nose,Mouth,Ear派生而成,那么Head将自动具有Look,Smell,Eat,Listen这些功能。

//错误的设计
class Head : public Eye,public Nose, public Mouth,public Ear {};

在这里插入图片描述

实心菱形代表了一种坚固的关系,被包含类的生命周期受包含类控制,被包含类会随着包含类创建而创建,消亡而消亡。组合属于黑盒复用,被包含对象的内部细节对外是不可见的,所以它的封装性相对较好,实现上相互依赖比较小,并且可以通过获取其他具有相同类型的对象引用或指针,在运行期间动态的定义组合。缺点就是使系统中的对象过多。

综上所述,is-A关系用继承表示,Has-A关系用组合表示,优先使用对象组合,而不是类继承。
转https://blog.csdn.net/K346K346/article/details/55045295

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值