2017-04-14 156 views
3

我与打字稿工作,我有带班打字稿,静态方法继承

之间的静态继承问题

谁能给我解释一下下面的结果:

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

当前的结果:

[ 'Hello', 'Both ?' ] 
[ 'World' ] 
[ 'Hello', 'Both ?' ] 

,但我想:

[ 'Hello' ] 
[ 'World' ] 
[ 'Both ?' ] 

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

谢谢!

+0

删除*静态* –

回答

5

有关OPs代码中行为的非常详细的解释,请参见answer in this thread by @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 ?'); 

code in playground

+1

记住'Map'可以有非字符串键,所以你可以通过构造函数自己键入...... :-) –

+0

@TJCrowder True。但我总是更喜欢使用“字符串ID”,除非我实际上需要实例(在这种情况下是构造函数)用于其他事情。这可能是我从其他语言中选择的一种偏好。 –

5

关于staticclass要理解的关键是,子类的构造函数从超类的构造函数继承。从字面上看。 class不是只是在构造函数创建的实例之间建立了继承关系,构造函数本身也是在继承结构中。

FooSonDaughter的原型。这意味着Daughter.barFoo.bar,它是一个继承的属性。但你给Son它的自己bar属性,用自己的数组,以便链接与Foo被打破。

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

将它们分开,你可能想需要给每个构造自己的bar,虽然你可以什么Nitzan Tomer suggestsMap


有关如何组织的更多细节。这是一个有点像这样:

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

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

 
              +−−>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 | 
             +−−−−−−−−−−−+