我的理解是静态方法的继承没有在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
类有几个子类,包括HttpWebRequest
和FtpWebReuest
。 现在,这种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?