【发布时间】:2021-09-26 09:19:33
【问题描述】:
假设您正在制作一个 GUI,并且有一个 DataViewList 类,它是一个显示数据行的小部件(例如 like this)。你有方法AddRow(std::vector<std::string> row)、DeleteRow(std::vector<std::string> row)和AddColumn(std::string name)、DeleteColumn(std::string name)。
现在假设您要创建一个显示音乐播放列表的新类。它具有预先确定的列(标题、专辑、年份),您不想添加任何新列或删除现有列。此外,您希望能够在单个方法调用中将 Song 对象添加到列表中,因此您需要一个可以做到这一点的方法。你如何实现这样的类?
最基本的想法是创建一个新类MusicPlaylsit,它公开继承DataViewList,并在构造函数中添加预定的列。然后重载AddRow 方法,使其接受Song 对象作为参数。这种方法有一个很大的问题:有人可能会调用MusicPlaylist::AddColumn 或其他与MusicPlaylist 类的逻辑不兼容的方法。由于 MusicPlaylist 应该只有三个预定义的列,所以不应该有添加或删除列的方法(或访问任何其他不兼容的基类方法,例如基类非重载的 AddRow 方法)。
为了解决这个问题,我可以使用组合而不是继承,并重新实现我可能想要使用的任何方法。在我看来,这是一个坏主意,因为如果我将来想更改某些内容,这比继承更困难,因为我无法覆盖基类方法。
另一个选项是继承为protected。这可以防止使用不兼容的基类方法,并允许在未来继承的情况下进行覆盖。问题是,现在我必须用using 明确声明我想公开使用的每个方法,这似乎违背了面向对象编程的全部观点(能够在深层基类中更改某些内容并且仍然有任何继承的类能够使用它)因为在DataViewList 中新添加的公共方法在MusicPlaylist 或任何从它继承的类中将不可见,直到它们被显式公开。
所以我的问题是:在创建与基类具有“是”关系但仅与其方法部分兼容的新类时,我应该使用哪种模式?
谢谢
【问题讨论】:
-
继承表示“A履行了B的契约”的关系。如果您的
DataViewList代表可编辑的列,而您的MusicPlaylist不可编辑,则MusicPlaylist不履行DataViewList的合同,不得继承它。 -
B的合同是什么意思?
标签: c++ oop inheritance design-patterns