是否可以将 methods/fields 放入仅由某些派生的 classes 使用的基础 class
Is it ok to put methods/fields to base class that will only be used by some of the derived classes
这是一个有点通用的软件设计问题。假设你有一个基础 class 和许多从它派生的 classes(大约 10 个)。
一些 classes 之间共享一些通用功能(派生的 classes 中有 3-4 个需要它)。基本上是一个UI控件的字段,一个创建UI控件的抽象方法和使用抽象方法回收UI块的公共代码(8-9行代码)使用抽象方法。像这样:
class BaseClass {
...
protected UIControl control;
protected abstract UIControl CreateUI();
protected void RecycleUI() {
if (/* some condition is met */) {
if (this.control != null) {
control.Dispose();
}
this.control = this.CreateUI();
this.AddToUITree(control);
}
}
...
}
您认为可以将其放入基础 class 而不是在派生 classes 中复制代码吗?
缺点是这段代码只用于一些基础 classes 而与其他 classes 完全无关。
一种替代方法是创建一个派生自 BaseClass 的中间体 class,并将其用作需要该功能的类的基础。我觉得为特定目的的几行代码创建一个派生的 class 感觉很沉重。感觉不值得为此打断继承树。我们尽量保持层次结构尽可能简单,以便于遵循和理解继承树。也许如果这是 C++,其中多重继承是一个选项,它不会是一个大问题,但多重继承不可用。
另一种选择是创建实用程序方法和 create/update UI 控件的接口:
interface UIContainer {
UIControl CreateUIControl();
UIControl GetUIControl();
void SetUIControl(UIControl control);
}
class UIControlUtil {
public void RecycleUI(UIContainer container) {
if (/* some condition is met */) {
if (container.GetUIControl() != null) {
container.GetUIControl().Dispose();
}
UIControl control = container.CreateUI();
container.SetUIControl(control);
container.AddToUITree(control);
}
}
}
我不喜欢这个选项,因为它会在外部泄漏 UI 逻辑,这不太安全,因为它的 UI 状态可以在外部进行操作。派生的 classes 现在必须实现 getter/setter。一个优点是在上述继承树之外还有另一个class,它需要这个功能,它也可以使用这个效用函数。
您还有其他建议吗?我是否应该抑制内心酝酿的不重复通用代码的冲动?
One alternative is to create an intermediate class that derives from
BaseClass and use it as the base to the ones that need the
functionality.
嗯,这是我认为最合适的。但这取决于。这里的主要问题如下:需要 UI 回收的对象与不需要回收的对象真的不同吗?如果它们真的不同,你必须为它们创建一个新的基础class。如果差异真的可以忽略不计,我认为把东西放在基数中是可以的class。
不要忘记 LSP。
We try to keep the hierarchy as simple as possible so that it is easy
to follow and understand the inheritance tree
我认为这里更重要的是不仅要保持简单,而且要接近现实世界的事物,以便为新实体建模很容易。现在看起来很容易,将来可能会带来真正的麻烦。
这是一个有点通用的软件设计问题。假设你有一个基础 class 和许多从它派生的 classes(大约 10 个)。
一些 classes 之间共享一些通用功能(派生的 classes 中有 3-4 个需要它)。基本上是一个UI控件的字段,一个创建UI控件的抽象方法和使用抽象方法回收UI块的公共代码(8-9行代码)使用抽象方法。像这样:
class BaseClass {
...
protected UIControl control;
protected abstract UIControl CreateUI();
protected void RecycleUI() {
if (/* some condition is met */) {
if (this.control != null) {
control.Dispose();
}
this.control = this.CreateUI();
this.AddToUITree(control);
}
}
...
}
您认为可以将其放入基础 class 而不是在派生 classes 中复制代码吗?
缺点是这段代码只用于一些基础 classes 而与其他 classes 完全无关。
一种替代方法是创建一个派生自 BaseClass 的中间体 class,并将其用作需要该功能的类的基础。我觉得为特定目的的几行代码创建一个派生的 class 感觉很沉重。感觉不值得为此打断继承树。我们尽量保持层次结构尽可能简单,以便于遵循和理解继承树。也许如果这是 C++,其中多重继承是一个选项,它不会是一个大问题,但多重继承不可用。
另一种选择是创建实用程序方法和 create/update UI 控件的接口:
interface UIContainer {
UIControl CreateUIControl();
UIControl GetUIControl();
void SetUIControl(UIControl control);
}
class UIControlUtil {
public void RecycleUI(UIContainer container) {
if (/* some condition is met */) {
if (container.GetUIControl() != null) {
container.GetUIControl().Dispose();
}
UIControl control = container.CreateUI();
container.SetUIControl(control);
container.AddToUITree(control);
}
}
}
我不喜欢这个选项,因为它会在外部泄漏 UI 逻辑,这不太安全,因为它的 UI 状态可以在外部进行操作。派生的 classes 现在必须实现 getter/setter。一个优点是在上述继承树之外还有另一个class,它需要这个功能,它也可以使用这个效用函数。
您还有其他建议吗?我是否应该抑制内心酝酿的不重复通用代码的冲动?
One alternative is to create an intermediate class that derives from BaseClass and use it as the base to the ones that need the functionality.
嗯,这是我认为最合适的。但这取决于。这里的主要问题如下:需要 UI 回收的对象与不需要回收的对象真的不同吗?如果它们真的不同,你必须为它们创建一个新的基础class。如果差异真的可以忽略不计,我认为把东西放在基数中是可以的class。
不要忘记 LSP。
We try to keep the hierarchy as simple as possible so that it is easy to follow and understand the inheritance tree
我认为这里更重要的是不仅要保持简单,而且要接近现实世界的事物,以便为新实体建模很容易。现在看起来很容易,将来可能会带来真正的麻烦。