继承和组合,究竟我要选哪个?
The following article is from 程序喵大人 Author 程序喵大人
来源丨经授权转自 程序喵大人(ID:chengxumiaodaren)
作者丨程序喵大人
[每日一题]栏目第二题,如图:
问题1:想让每个类对象都有一个唯一的ID,有什么优雅的设计?
首先肯定要设计一个管理对象ID的类,即:
struct Object {
int64_t GetId();
};
那如何将Object与其他类对象关联?可能有这两种方式:
///< 方式1:继承
struct A : Object {};
struct B : Object {};
///< 方式2:组合
struct A {
int64_t GetId() { return obj_.GetId(); }
private:
Object obj_;
};
继承和组合两种方式?选择哪种更好?
问题2:音视频中,视频基本上包含音频,音频有的属性,视频也有。例如,音频可以设置音量,视频视频包含音频,那我如果也想设置音量,可能有两种方式。
组合方式如下:
struct Audio {
void SetVolume();
};
struct Video : Audio {};
struct Video {
void SetVolume();
private:
Audio audio_;
};
继承方式如下:
struct Audio {
void SetVolume();
};
struct Video : Audio {};
那应该怎么选择?
这两个问题其实可以归为一类问题,选择组合还是继承?
tips1:这里说的视频不是音视频专业领域的视频轨,而是我们通常意义上的视频容易,既包含音频轨道也包含视频帧画面。
tips2:也许大家说,这不显而易见吗,区分has a还是 is a,has a就用组合方式,is a就用继承方式。
上面的代码大家也看见了,遵循书本上的说法应该使用组合方式,可如果使用继承方式貌似会非常的方便。
如果Audio类有上百个方法,继承方式几行代码就能搞定,而组合方式,却需要重新在Video上暴露上百个方法,然后在实现中调用Audio的相关方法。(除非把audio变成public成员,变成video.audio.SetVolume,这对用户调用貌似不太友好,用户想要的是直接设置视频音量。)
这貌似很麻烦,我们真的要严格的遵循has a组合、is a继承的定式吗?
组合的缺点:
更多的接口,更多的维护成本。
继承的缺点:
层次过多后,代码可读性差、不好维护
可能很多朋友都厌恶继承,特别是C++中,很多朋友都把继承当作个洪水猛兽,不敢触碰,严格遵循多用组合少用继承的套路。
个人认为,没必要死扣字眼。固定编程范式。
多用组合、少用继承这种定式并不是绝对的,可以根据实际情况适当调整,控制好副作用,发挥各自的优势。
一般使用继承都是为了方便应对频繁变化的需求。但如果继承结构稳定,层次不多,最多两层,那可以大胆的尝试用继承,会更加方便。
回到上面的问题,即便它是has a的关系,但是因为使用组合方式带来的成本过高,而且它的继承层次只有一层,因此我倾向于使用继承方式。
至于has a还是is a,可以改个名字再看一看:
struct Media {
void SetVolume();
};
struct Audio : Media {};
struct Video : Media {};
嗯,这就是is a了。
以上仅代表个人观点,也不一定对,大家多提宝贵建议哈。
3、静态代码块、构造代码块、构造函数、普通代码块,还傻傻的分不清?
点分享
点点赞
点在看