继承静态变量,按类区分?

3
我正在处理这样一种情况:我想有一个特定的基类,定义一个静态关联数组和与其相关的静态函数,然后在继承它的类中复制这个功能,但每个子类都拥有自己的数组实例。然而,似乎子类只是继承了父类的数组,而不是像我希望的那样创建它们自己的静态副本。以下是我希望实现的超级简化剥离版本:
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"]

有没有一种方法可以避免放弃继承,而只是为每个子类复制相关代码?我正在使用的分配数组的实际代码比上面列出的attach函数更加复杂,因此我想避免每次都重复它,或者必要时手动分配到.dict。我想知道是否有涉及模板的解决方案可能会起作用,但我似乎无法将其组合在一起。

3个回答

6
在一个类中,静态变量是该类的一部分,且仅为该类的一部分。无论创建了多少个该类的实例或从中派生了多少个类,程序中都存在一个该变量的实例。与普通成员变量一样,静态成员变量也不会被继承。如果基类的变量是公共的或受保护的,则派生类可以访问它,但它们不会获得自己的副本。在派生类链中,没有任何东西被复制。成员变量存在于它们声明的类中,派生类可能可以访问它们,但派生类不会获得自己的副本。
因此,将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);
}

1
啊,看起来我刚刚偶然发现了解决方案。
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 {
    // ...
}

完全符合我的要求。根据快速礼仪搜索,发布自己的答案。


2
只是让你知道,MySubAMySubB不会以这种方式共享相同的基类。它们位于完全独立的类层次结构中,因为MyBase!MySubAMyBase!MySubB是不同的类。同一模板的不同实例是完全独立的实体,彼此之间没有关系。 - Jonathan M Davis
2
如果类层次结构实际上不是必需的(仅用于提供字典实现),那么我会说模板混合是正确的选择。 - Mihails Strasuns
+1 绝对正确。@ccjuju,如果你只是为了避免一点重复而使用继承,那就不要这样做,使用泛型。另一方面,如果这些类确实代表一个对象层次结构,那么你发布的解决方案并没有达到你所要求的效果。 - Tim

0

如果您不需要层次结构:

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

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


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