关于列表项及其类设计的意见

时间:2009-09-19 14:52:22

标签: c++ oop inheritance widget

我目前正在设计一个列表小部件,以添加到我的小部件引擎中。由于每个元素的可视方面都是在代码之外定义的,因此我可以重用大部分代码库。例如,选项卡按钮实际上是复选框。新模板需要时间来实现,因为它们在设计应用程序中至少应该有一个查看器。

我已经有了一个复选框的实现。它有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) {
 }

这可以解决很多问题。欢迎任何想法。

感谢您阅读所有这些

2 个答案:

答案 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

您怎么看?