什么是静态方法继承的正确替代方法?

Tim*_*ter 79 .net c# inheritance static

我知道C#不支持静态方法继承.我还阅读了许多讨论(包括此处),其中开发人员声称需要此功能,典型的响应是"如果您需要静态成员继承,那么您的设计就存在缺陷".

好吧,鉴于OOP不希望我甚至考虑静态继承,我必须得出结论,我对它的明显需求指出了我的设计中的错误.但是,我被困住了.我真的很感激帮助解决这个问题.这是挑战......

我想创建一个抽象基类(我们称之为Fruit),它封装了一些复杂的初始化代码.此代码不能放在构造函数中,因为其中一些代码将依赖于虚方法调用.

Fruit将由其他具体类(Apple,Orange)继承,每个类必须公开标准工厂方法CreateInstance()以创建和初始化实例.

如果静态成员继承是可行的,我会将工厂方法放在基类中,并使用对派生类的虚方法调用来获取必须从中初始化具体实例的类型.客户端代码可以简单地调用Apple.CreateInstance()来获取完全初始化的Apple实例.

但显然这是不可能的,所以有人可以解释我的设计需要如何改变以适应相同的功能.

Mat*_*ith 59

一个想法:

public abstract class Fruit<T>
    where T : Fruit<T>, new()
{
    public static T CreateInstance()
    {
        T newFruit = new T();
        newFruit.Initialize();  // Calls Apple.Initialize
        return newFruit;
    }

    protected abstract void Initialize();
}

public class Apple : Fruit<Apple>
{
    protected override void Initialize() { ... }
}
Run Code Online (Sandbox Code Playgroud)

并且这样打电话:

Apple myAppleVar = Fruit<Apple>.CreateInstance();
Run Code Online (Sandbox Code Playgroud)

不需要额外的工厂类.

  • 恕我直言,最好将泛型类型移动到CreateInstance方法,而不是将其放在类级别.(就像我在答案中所做的那样). (8认同)
  • 通过这样做,你不会"污染"其余的课程; type参数仅在Create方法中必需(至少在此示例中).接下来,我认为:Fruit.Create <Apple>(); 更可读的是:Fruit <Apple> .Create(); (7认同)
  • 你不能使`Apple`构造函数小于public,因为`where T:Fruit <T>,new()`表明`T`必须有一个公共构造函数.@Matt Hamsmith - 在删除`protected Apple(){}之前,你的代码不能编译.我已经在VS中测试了它. (2认同)

Fre*_*els 16

将工厂方法移出类型,并将其放在自己的Factory类中.

public abstract class Fruit
{
    protected Fruit() {}

    public abstract string Define();

}

public class Apple : Fruit
{
    public Apple() {}

    public override string Define()
    {
         return "Apple";
    }
}

public class Orange : Fruit
{
    public Orange() {}

    public override string Define()
    {
         return "Orange";
    }
}

public static class FruitFactory<T> 
{
     public static T CreateFruit<T>() where T : Fruit, new()
     {
         return new T();
     }
}
Run Code Online (Sandbox Code Playgroud)

但是,正如我在看这个,没有必要将Create方法移动到它自己的Factory类(虽然我认为它是可取的 - 关注点分离 - ),你可以把它放在Fruit类中:

public abstract class Fruit
{

   public abstract string Define();

   public static T CreateFruit<T>() where T : Fruit, new()
   {
        return new T();
   }

}
Run Code Online (Sandbox Code Playgroud)

并且,看它是否有效:

    class Program
    {
        static void Main( string[] args )
        {
            Console.WriteLine (Fruit.CreateFruit<Apple> ().Define ());
            Console.WriteLine (Fruit.CreateFruit<Orange> ().Define ());

            Console.ReadLine ();
        }        
    }
Run Code Online (Sandbox Code Playgroud)