【问题标题】:D: Inheriting static variables, differentiating by class?D:继承静态变量,按类区分?
【发布时间】:2012-07-17 04:35:01
【问题描述】:

我正在处理这样一种情况,我希望有一个特定的基类,该基类定义一个静态关联数组和使用它的静态函数,然后在从它继承的类中复制此功能,但每个具有自己的数组实例的子类。但是,看起来子类只是继承了父类的数组,而不是像我希望的那样创建自己的静态副本。以下是我希望完成的超级简化的精简版:

class MyBase {
    static string[string] dict;
    static void attach(string key, string val) {
        dict[key] = val;
    }
}
class MySubA : MyBase {
    // various unique member variables
}
class MySubB : MyBase {
    // ...
}
void main() {
    MySubA.attach("a", "a1");
    MySubB.attach("b", "b1");
    writefln("-:%s", MyBase.dict);
    writefln("A:%s", MySubA.dict);
    writefln("B:%s", MySubB.dict);
}

期望的输出:

-:[]
A:["a":"a1"]
B:["b":"b1"]

实际输出:

-:["a":"a1", "b":"b1"]
A:["a":"a1", "b":"b1"]
B:["a":"a1", "b":"b1"]

有没有办法在不放弃继承而只为每个子类复制相关代码的情况下解决这个问题?分配给我正在使用的数组的实际代码比上面列出的附加函数更复杂,所以我想避免每次都复制它,或者在必要时手动分配给 .dict 。我想知道是否有一个涉及模板的解决方案可能有效,但我似乎无法将它拼凑在一起。

【问题讨论】:

    标签: inheritance static-methods static-members d


    【解决方案1】:

    类中的静态变量是该类的一部分,并且只是该类的一部分。无论创建了多少个该类的实例或从它派生了多少类,整个程序中都存在它的一个实例。没有静态成员变量的继承,就像普通成员变量的继承一样。如果基类变量是公共的或受保护的,派生类可以访问它,但它们没有自己的副本。 Nothing 被复制到一个派生类链中。成员变量存在于声明它们的类中,派生类可能可以访问它们,但派生类没有自己的副本。

    因此,通过将dict 放入MyBase,您为整个程序创建了其中一个,无论其派生类做什么。如果您希望每个派生类都有自己的副本,那么它们每个都必须声明自己的一个。

    现在,您可以通过模板 mixin 或字符串 mixin 最大限度地减少代码重复,但您仍然必须将其混合到每个派生类中。例如,您可以这样做

    import std.stdio;
    
    mixin template Dict()
    {
        static string[string] dict;
        static void attach(string key, string val)
        {
            dict[key] = val;
        }
    }
    
    class MyBase
    {
        mixin Dict;
    }
    
    class MySubA : MyBase
    {
        mixin Dict;
        // various unique member variables
    }
    
    class MySubB : MyBase
    {
        mixin Dict;
        // ...
    }
    
    void main()
    {
        MySubA.attach("a", "a1");
        MySubB.attach("b", "b1");
        writefln("-:%s", MyBase.dict);
        writefln("A:%s", MySubA.dict);
        writefln("B:%s", MySubB.dict);
    }
    

    【讨论】:

      【解决方案2】:

      啊,看来我只是偶然发现了解决方案。

      class MyBase(T) {
          static string[string] dict;
          static void append(string key, string val) {
              dict[key] = val;
          }
      }
      class MySubA : MyBase!MySubA {
          // various unique member variables
      }
      class MySubB : MyBase!MySubB {
          // ...
      }
      

      正是我想要的。根据快速礼仪搜索发布自己的答案。

      【讨论】:

      • 请注意,MySubAMySubB 不会以这种方式共享同一个基类。它们位于完全独立的类层次结构中,因为 MyBase!MySubAMyBase!MySubB 是不同的类。同一模板的不同实例是完全独立的实体,彼此没有关系。
      • 如果实际上不需要类层次结构(并且仅用于提供 dict 实现),那么我会说模板混合是要走的路。
      • +1 绝对。 @ccjuju,如果您只是使用继承来避免一些重复,请不要使用泛型。另一方面,如果这些类确实表示对象层次结构,那么您发布的解决方案不会满足您的要求。
      【解决方案3】:

      如果你不需要层次结构:

      import std.stdio;
      
      mixin template Dict()
      {
          static string[string] dict;
          static void attach(string key, string val)
          {
              dict[key] = val;
          }
      }
      
      class MySubA
      {
          mixin Dict;
      }
      
      class MySubB
      {
          mixin Dict;
      }
      
      void main()
      {
          MySubA.attach("a", "a1");
          MySubB.attach("b", "b1");
          writefln("A:%s", MySubA.dict);
          writefln("B:%s", MySubB.dict);
      }
      

      我认为这是比这种模板继承更好的解决方案。

      【讨论】:

        猜你喜欢
        • 2020-10-18
        • 2011-08-05
        • 1970-01-01
        • 1970-01-01
        • 2016-09-10
        • 2017-01-10
        • 2019-04-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多