Typescript,静态方法继承

vin*_*ron 8 javascript typescript ecmascript-6 typescript2.0

我正在使用typescript,我对类之间的静态继承有问题

任何人都可以解释以下结果:

class Foo {
    protected static bar: string[] = [];

    public static addBar(bar: string) {
        this.bar.push(bar);
    }

    public static logBar() {
        console.log(this.bar);
    }
}

class Son extends Foo {
    protected static bar: string[] = [];
}

class Daughter extends Foo {}

Foo.addBar('Hello');
Son.addBar('World');
Daughter.addBar('Both ?');
Foo.logBar();
Son.logBar();
Daughter.logBar();
Run Code Online (Sandbox Code Playgroud)

目前的结果:

[ 'Hello', 'Both ?' ]
[ 'World' ]
[ 'Hello', 'Both ?' ]
Run Code Online (Sandbox Code Playgroud)

但我想要 :

[ 'Hello' ]
[ 'World' ]
[ 'Both ?' ]
Run Code Online (Sandbox Code Playgroud)

我有没有重新声明静态bar属性的解决方案吗?

谢谢 !

T.J*_*der 12

最关键的事情都懂staticclass是子类的构造函数继承自父类的构造函数.从字面上看.class只是在构造函数创建的实例之间建立继承,构造函数本身也在继承结构中.

Foo是的原型SonDaughter.这意味着Daughter.bar Foo.bar,这是一个继承财产.但是你给Son自己的 bar属性,有自己的数组,所以链接Foo被打破了.

这就是为什么你看到的["Hello", "Both ?"],当你在Foo.barDaughter.bar:这是相同的bar,在同一阵列指向.但是,你只能看到["World"]Son.bar,因为它是一个不同的bar,在不同的阵列指向.

将它们分开,你可能想需要给每个构造自己的bar,但是你可以做什么Nitzan托梅尔建议Map.


关于事物如何组织的更多细节.它有点像这样:

const Foo = {};
Foo.bar = [];
const Son = Object.create(Foo);
Son.bar = []; // Overriding Foo's bar
const Daughter = Object.create(Foo);
Foo.bar.push("Hello");
Son.bar.push("World");
Daughter.bar.push("Both ?");
console.log(Foo.bar);
console.log(Son.bar);
console.log(Daughter.bar);
Run Code Online (Sandbox Code Playgroud)

如果你是新鲜的,这是一个非常令人惊讶的事情,但你的三个类在内存中看起来像这样:

                                             +??>Function.prototype 
                          +???????????????+  |
Foo??????????????????+?+?>|   (function)  |  |       
                    / /   +???????????????+  |       
                    | |   | [[Prototype]] |??+       +???????????+
                    | |   | bar           |?????????>|  (array)  |
                    | |   | addBar, etc.  |          +???????????+
                    | |   +???????????????+          | length: 2 |
                    | |                              | 0: Hello  |
                    | +?????????????+                | 1: Both ? |
                    |               |                +???????????+
                    +????????????+  |
                                 |  |
              +???????????????+  |  |
              |   (function)  |  |  |    
              +???????????????+  |  |    
Daughter?????>| [[Prototype]] |??+  |
              +???????????????+     |
                                    |
              +???????????????+     |
              |   (function)  |     |       
              +???????????????+     |       
Son??????????>| [[Prototype]] |?????+    +???????????+
              | bar           |?????????>|  (array)  |
              +???????????????+          +???????????+
                                         | length: 1 |
                                         | 0: World  |
                                         +???????????+


Nit*_*mer 8

关于OPs代码中行为的非常详细的解释可以在@TJCrowder的回答中找到.

为了避免重新定义静态成员,您可以采用以下方法:

class Foo {
    private static bar = new Map<string, string[]>();

    public static addBar(bar: string) {
        let list: string[];

        if (this.bar.has(this.name)) {
            list = this.bar.get(this.name);
        } else {
            list = [];
            this.bar.set(this.name, list);
        }

        list.push(bar);
    }

    public static logBar() {
        console.log(this.bar.get(this.name));
    }
}

class Son extends Foo {}

class Daughter extends Foo {}

Foo.addBar('Hello');
Son.addBar('World');
Daughter.addBar('Both ?');
Run Code Online (Sandbox Code Playgroud)

(游乐场代码)

  • 请记住,“Map”可以具有非字符串键,因此您可以仅通过构造函数本身进行键...:-) (2认同)