获取静态成员

3

我有一个基类,其中包含一个私有静态成员:

class Base
{
    private static Base m_instance = new Base();
    public static Base Instance
    {
        get { return m_instance; }
    }
}

我希望从这个类派生多个类:

class DerivedA : Base {}
class DerivedB : Base {}
class DerivedC : Base {}

然而,此时调用DerivedA::Instance将返回与DerivedB::Instance和DerivedC::Instance完全相同的对象。我可以通过在派生类中声明实例来解决这个问题,但这样每个派生类都需要这样做,似乎是不必要的。那么有没有办法将所有这些放在基类中?是否可以应用一种设计模式?

3个回答

11

有一种非常恶心的方法可以做到这一点:

class Base
{
     // Put common stuff in here...
}

class Base<T> : Base where T : Base<T>, new()
{
    private static T m_instance = new T();

    public static T Instance { get { return m_instance; } }
}

class DerivedA : Base<DerivedA> {}
class DerivedB : Base<DerivedB> {}
class DerivedC : Base<DerivedC> {}

这段代码的实现依赖于每个构造类型都有一个静态变量,例如List<string>List<int>是不同的类型,因此会有独立的静态变量。
我也将其作为派生类的实例,但我不确定这是否符合您的要求,但我至少将其提供给您 :)
总的来说,这种做法并不好。静态变量并不是为这种用途而设计的——我只是滥用了泛型的一项特性,以实现您所需的“类似”的行为。
还要注意,Base<DerivedA>.Instance将返回与DerivedA.Instance相同的结果——属性/变量并不知道您正在使用DerivedA.Instance。我不知道这对您是否重要。
通过额外的非泛型类,您可以编写如下代码:
Base t = DerivedA.Instance;
t = DerivedB.Instance;

如果您不需要它,请将其移除 :)

哈哈,有人给你点了踩,这是我第一次见到! :) - leppie
是的,我知道你说这个方法不太好。但是我想提醒一下,如果您使用此方法,则将无法执行“Base x = DerivedA.Instance;”,这可能是必要的。 - Mehrdad Afshari
以下是关于编程的内容,请将其翻译成中文。请只返回翻译后的文本: - Jon Skeet
这很尴尬 - 他正在创建不是单例的单例。这让我想到了重构,我认为JS(以及每个人)应该被允许在回应中有些灵活性,只要明确表明这是不好的。 - annakata
病人:医生,我做这个动作时手臂很疼。医生:那就不要做那个动作。伙计,我不确定你想达到什么目的,但我打赌100万美元有更好的方法。支持James的观点。Mike,相信我,你不想这样做。 - Binary Worrier
显示剩余6条评论

6

静态方法不支持多态,因此这种事情是不可能的。

从根本上讲,Instance属性不知道你如何使用它。并且只有一个实现它的静态方法存在。如果您真的想要做到这一点,可以使用这个“不推荐”的解决方案(我从Jon的解决方案得到了灵感):

private static Dictionary<Type, Base> instances = new Dictionary<Type, Base>();
public static T GetInstance<T>() where T : Base, new() {
  Type ty = typeof(T);
  T x;
  if (instances.TryGetValue(ty, out x)) return x;
  x = new T();
  instances[ty] = x;
  return x;
}

3
简短回答:据我所知,不支持。静态成员始终是非虚拟的,并且不容易支持多态性。
然而,你也应该问自己为什么要这样做。通常,静态成员是每个类实例(包括派生类)都会发现有用的共享资源。但是,当你创建一个静态实例时,通常是在构建单例模式。在这种情况下,您通常希望封闭类,以便不能有派生类,从而使整个目的无意义。因此,你应该真正分析为什么想要这样做并解决那个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接