我目前正在设计一个列表小部件,以添加到我的小部件引擎中。由于每个元素的可视方面都是在代码之外定义的,因此我可以重用大部分代码库。例如,选项卡按钮实际上是复选框。新模板需要时间来实现,因为它们在设计应用程序中至少应该有一个查看器。
我已经有了一个复选框的实现。它有2个状态(已检查/未检查)和5个子状态:正常,悬停/活动,mousedown,禁用和状态转换。复选框模板具有文本属性,图标(可选)和边框(可以调整大小)。还有状态和子状态转换。图标和边框都是可动画的。
我关心的是列表项目。它们与复选框非常相似。因此,我打算使用复选框模板列表项目。但是,我需要列表项的四种模式:简单(仅文本),带图标,带复选框和单选按钮(单选按钮来自复选框和IRadioButton界面)。这是它的结构:
IWidgetObject
|
Checkbox IRadioButton
\ /
`--------------´
|
RadioButton
我希望实现这样的事情。 ListItemBase应该从IWidgetObject派生。这是合乎逻辑的还是有更好的选择。
class ListItemBase : public Checkbox {
void Select() { do something; Checkbox::check(); }
}
//This listitem type will have a checkbox without any text
class ListItemCheckbox : public ListItemBase, private Checkbox {
check() { update parents checked list; Checkbox::check(); }
}
class ListItemRadio : public ListItemBase, private RadioButton, public IRadioButton {
//here is the problem
}
ListItemRadio将有2个不同的复选框功能,我也想隐藏ListItemBase的check()函数(重命名)。那我应该这样实现吗?
class ListItemBase : private Checkbox, public IWidgetObject {
void Select() { do something; Checkbox::check(); }
//does this even works? (layer is a variable)
using Checkbox::layer;
}
//This listitem type will have a checkbox without any text
class ListItemCheckbox : public ListItemBase, private Checkbox {
check() { update parents checked list; Checkbox::check(); }
}
class ListItemRadio : public ListItemBase, private RadioButton, public IRadioButton {
//here is the problem
}
但这次我在ListItemRadio中有2个IWidgetObjects,我应该克服它实现常用功能。但是ListItemBase必须将IWidgetObject的所有内容映射到Checkbox。
是否可以使用虚拟继承来解决这些问题,例如委托给姐妹类(复选框)。还有一个问题,虽然IWidgetObject看起来像一个接口,多年来它采用了一些常见的实现,但我不认为这将是一个问题。
还有一个问题。 Checkbox类有非平凡的构造函数。有可能写出这样的东西:
ListItemBase(IWidgetContainer &container, CheckboxBP &blueprint) :
Checkbox(container, blueprint), IWidgetObject(this) {
}
这可以解决很多问题。欢迎任何想法。
感谢您阅读所有这些
答案 0 :(得分:2)
我不知道你的“小工具引擎”和“模板”的细节,所以也许你设计的方式现在强迫你的手(我希望不会!),但在我看来,你呢?重新使用继承,而自然设计将使用包含和组合 - 一个更好的解决方案。即,你说的是一个列表项“IS-A”复选框,而自然状态是列表项“HAS-A”复选框(对于单选按钮也类似)。
如果你被迫通过widget引擎的设计以这种方式运行,那么你最终需要多重继承就不足为奇了 - 但这会增加它自身的复杂性,而且,无论如何,子类化导致强耦合和低灵活性,而遏制和组合在这些方面更好。我建议阅读经典的Design Patterns,它可以很好地解释这些问题。
无论如何,如果 被困在这种设计中,那么,是的, 可能,如你所说,写:
ListItemBase(IWidgetContainer &container, CheckboxBP &blueprint) :
Checkbox(container, blueprint), IWidgetObject(this) {
}
然而,这并不意味着Checkbox基类构造函数在IWidgetObject之前执行:这取决于您声明基础的顺序(如果您将IWidgetObject声明为第一个基础,其构造函数将在另一个之前执行)
答案 1 :(得分:0)
好的,我提出了一个想法
IWidgetObject
|
ICheckbox CheckboxBase IRadioButton
| \ / | \ / |
| `-------------´ | `---------´ |
| | | | |
| Checkbox | RadioButton |
| | |
| ListItemBase |
\ | | /
`---------------´ `--------------´
| |
ListItemCheckbox ListItemRadioButton
您怎么看?