什么是静态方法继承了正确的选择吗?(What's the correct alternati

2019-06-21 20:49发布

我的理解是静态方法的继承没有在C#的支持。 我也看到了一些讨论(包括这里),其中开发者声称需要这个功能,到典型的反应是:“如果你需要的静态成员的继承,有一个在你的设计中的缺陷”。

OK,既然OOP不想让我别想静态的继承,我必须得出结论,我为它明显需要指出我的设计错误。 但是,我坚持。 我真的很感激一些帮助解决这一点。 这里的挑战...

我想创建一个抽象基类(姑且称之为水果),它封装了一些复杂的初始化代码。 此代码不能放置在构造函数中,因为它的一些将依靠虚拟方法调用。

果将被其他具体类(苹果,桔子),其每一个必须暴露一个标准工厂方法CreateInstance()来创建和初始化一个实例被继承。

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

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

Answer 1:

一个想法:

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() { ... }
}

并呼吁像这样:

Apple myAppleVar = Fruit<Apple>.CreateInstance();

无需额外的工厂类需要。



Answer 2:

移动工厂方法出来的类型,并把它放在自己的工厂类。

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();
     }
}

但是,正如我在看这个,就没有必要转移到自己的工厂类的创建方法(虽然我认为这是concerns-的preferrable -separation),你可以把它放在水果类:

public abstract class Fruit
{

   public abstract string Define();

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

}

而且,看看它的工作原理:

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

            Console.ReadLine ();
        }        
    }


Answer 3:

为什么不创建一个工厂类(模板)与创建方法?

FruitFactory<Banana>.Create();


Answer 4:

我会做这样的事情

 public abstract class Fruit() {
      public abstract void Initialize();
 }

 public class Apple() : Fruit {
     public override void Initialize() {

     }
 }

 public class FruitFactory<T> where T : Fruit, new {
      public static <T> CreateInstance<T>() {
          T fruit = new T();
          fruit.Initialize();
          return fruit;  
      }
 } 


var fruit = FruitFactory<Apple>.CreateInstance()


Answer 5:

所述WebRequest类及其衍生物的类型在.NET BCL代表的这种设计的如何可以实现相对较好的好例子。

WebRequest类有几个子类,包括HttpWebRequestFtpWebReuest 。 现在,这种WebRequest基类也是一个工厂类型,并公开一个静态Create方法(实例构造是隐藏的,所要求的工厂模式)。

public static WebRequest Create(string requestUriString)
public static WebRequest Create(Uri requestUri)

Create方法返回一个特定实现的WebRequest类,并使用URI(或URI字符串)来确定对象的类型来创建并返回。

这有以下使用模式的最终结果:

var httpRequest = (HttpWebRequest)WebRequest.Create("http://stackoverflow.com/");
// or equivalently
var httpRequest = (HttpWebRequest)HttpWebWebRequest.Create("http://stackoverflow.com/");

var ftpRequest = (FtpWebRequest)WebRequest.Create("ftp://stackoverflow.com/");
// or equivalently
var ftpRequest = (FtpWebRequest)FtpWebWebRequest.Create("ftp://stackoverflow.com/");

我个人认为这是处理这一问题的好办法,而且它确实似乎是在.NET Framework创建者的优先停留方法。



Answer 6:

首先,没有静态初始化,可以是虚拟的,并不意味着你不能有“标准”的成员方法,这可能是超载。 其次重要的是,你可以打电话给你的虚拟方法从构造器,它们会如预期,因此在这里没有任何问题。 第三重要的是,你可以使用泛型有类型安全的工厂。
下面是一些代码,使用由构造器调用工厂+成员初始化()方法(和它的保护,所以你不必担心,有人会创建一个对象后,再次称呼它):


abstract class Fruit
{
    public Fruit()
    {
        Initialize();
    }

    protected virtual void Initialize()
    {
        Console.WriteLine("Fruit.Initialize");
    }
}

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

    protected override void Initialize()
    {
        base.Initialize();
        Console.WriteLine("Apple.Initialize");
    }

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

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

    protected override void Initialize()
    {
        base.Initialize();
        Console.WriteLine("Orange.Initialize");
    }

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

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

public class Program
{

    static void Main()
    {
        Apple apple = FruitFactory.CreateFruit<Apple>();
        Console.WriteLine(apple.ToString());

        Orange orange = new Orange();
        Console.WriteLine(orange.ToString());

        Fruit appleFruit = FruitFactory.CreateFruit<Apple>();
        Console.WriteLine(appleFruit.ToString());
    }
}


Answer 7:

我说做的最好的事情是建立在水果类必须调用,然后创建一个外部“水果工厂”类创建实例虚拟/抽象初始化方法:


public class Fruit
{
    //other members...
    public abstract void Initialise();
}

public class FruitFactory()
{
    public Fruit CreateInstance()
    {
        Fruit f = //decide which fruit to create
        f.Initialise();

        return f;
    }
}


文章来源: What's the correct alternative to static method inheritance?