2017-04-14 3 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 코드의 동작에 대한 자세한 설명은 @TJCrowder가 answer in this thread에 있습니다.,

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

은'지도'가 아닌 문자열 키를 가질 수 있음을 기억 제거 :

은이 방법을 수행 할 수있는 정적 멤버를 재정의 할 필요성을 방지하려면 그래서 당신은 생성자 자체에 의해 단지 열쇠 일 수 있습니다. :-) –

+0

@TJCrowder True. 그러나 나는 실제로 "문자열 id"를 사용하는 것을 선호하는데, 실제로 다른 것들을위한 인스턴스 (이 경우에는 생성자)가 필요하지 않습니다. 그것은 아마도 내가 다른 언어에서 가지고 다니는 선호입니다. –

5

중요한 것은 약 staticclass는 서브 클래스 의 생성자 함수가 수퍼 클래스의 생성자 함수에서을 상속 이해합니다. 말 그대로. class이 아니며 단지이 생성자에 의해 생성 된 인스턴스간에 상속을 설정하면 생성자 도 상속 구조에 있습니다.

FooSonDaughter의 프로토 타입입니다. 즉 Daughter.barFoo.bar이며 상속 된 속성입니다. 그러나 Son자신의bar 속성을 할당하고 Foo의 링크가 깨졌습니다. 그것은 같은 배열을 가리키는, 같은 bar : 당신이 Foo.barDaughter.bar 볼 때 ["Hello", "Both ?"]을 볼 이유

는 그입니다. 하지만 다른 배열을 가리키는 다른 bar이기 때문에 Son.bar["World"] 만 표시됩니다. 당신이 무엇 Nitzan Tomer suggestsMap로 할 수 있지만

을 구분하려면, 당신은 아마 각 생성자에게 bar 자체를 제공해야합니다.


일이 어떻게 구성되어 있는지 조금 더 자세히 설명해주세요. 당신이 신선한 올 경우

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