c#类设计-实例独立信息

本文关键字:实例 独立 信息 | 更新日期: 2023-09-27 17:54:15

我遇到了一个类设计难题:我有一个泛型基类和多个派生类。基类是一个提供公共功能的CRTP类,其中一些功能需要继承特定于类的数据。因此,基类是抽象的,子类必须实现某些"提供者"方法。例如:

public abstract class Base<T> where T : Base<T>, new() {
    private static T reference = new T();
    public static int Foo => reference.GetFoo();
    public static string Bar => reference.GetBar();
    protected abstract int GetFoo();
    protected abstract string GetBar();
    // ...
}

问题是该信息不是特定于实例的,应该可以从泛型参数访问。使用上面的例子,这个方法可以在另一个类中:

public void ComputeSomething<T>() where T : Base<T>, new() {
    int foo = Base<T>.Foo;
    // ...
}

或者如果子类是已知的:ChildClass.Foo

这是可行的,但总的来说,这个解决方案感觉很"脏",因为我讨厌用类型信息弄乱每个实例,并且基类必须保持一个reference实例(如何在其基类中创建子类仍然让我有点挠头,通常看起来像个坏主意)。我会把信息放在缓存或工厂之类的地方,但我不能控制所有的子类,所以系统必须是可扩展的。我考虑过使用属性,但是(据我所知)没有办法在编译时强制使用某些属性。真的,我觉得我需要静态接口或静态抽象成员,但c#没有这些。

所以我的问题是:这类问题通常是如何解决的?

c#类设计-实例独立信息

我开始认为我需要一个单独的提供商类或其他

这就是答案。每当我进入这些复杂的泛型继承场景时,问题就在于我是通过继承而不是组合来组合类的。这就是为什么你会听到"优先组合而不是继承"的原则。

无论派生类需要从基类获得什么,它真的需要通过继承获得吗?还是可以通过创建一个单独的类并依赖于它来获得?

如果多个派生类将依赖于同一个类(这表明了继承的情况),那么可能可以将单独的类依赖构建到基类中。但它仍然是一个独立的类。派生类继承对的依赖,而不是继承实际的方法和属性。

我发现继承通常是重构的结果,可能是重构重复代码的一种方法(或者在它开始之前停止它)。当我一开始就认为我要预先重用代码时,结果很可能会变得太复杂。也许是因为我们仍然在编写类并决定它们如何工作。试图建立一个层次结构迫使我们预先假设太多,然后放弃设计是令人沮丧的。在事后进行重构或者考虑添加可能重复代码的新类时,它会更好地工作。

但是,即使在我添加新类并且不想复制代码的情况下,我也可能考虑将重复的代码重构到它自己的类中,而不是让新类继承现有的类。