是否可以将 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

我认为这里更重要的是不仅要保持简单,而且要接近现实世界的事物,以便为新实体建模很容易。现在看起来很容易,将来可能会带来真正的麻烦。