2017-01-10 9 views
1

私はそうのような基本的な継承があります。Typescriptは親クラスのプロパティを認識しませんか?

export abstract class Animal 
{ 
    constructor() { 

    } 

    makeSound() { 
     alert(this.sound); 
    } 
} 

export class Dog extends Animal 
{ 
    public sound: string = "Woof!"; 

    constructor() { 
     super(); 
    } 
} 

const dog = new Dog; 
dog.makeSound(); // Woof! 

は、私は上記のスニペットの作業を取得しようとしている問題を抱えているが。 Property prop does not exist on type A。しかし、それはBに存在し、公開されているので、Aはthis.prop経由で小道具に到達できるはずです。

私は次のことを試してみました:上記と

  • 同じ - それはコンパイルされません。 (プロパティーの小道具はタイプAにはありません)
  • public prop: any;Aを追加すると、propはでなく、Hello worldになります。
  • public abstract prop: any;Aを追加しても同じことが起こります。

抽象クラスを使用して継承の全ポイントを共有するのは、thisスコープです。

Typescriptで正しく行うにはどうすればよいですか?ここで

+0

です。リンゴ(B)は果物(A)ですが果物はリンゴがありません。 継承により動作が追加または変更されます。あなたのBはAにプロパティを追加します。したがって、Aにはプロパティがありません。 – chris01

+0

@chris詳しい説明は? – Aris

+2

あなたはAのインスタンスもBのインスタンスであると仮定しています。それは真実ではない: 'C extends A {}'はAを拡張し、propプロパティを持たないクラスを定義する。 –

答えて

4

私はJB Nizetに同​​意します。しかし、抽象的なプロパティとしてsoundを定義することもできます。そうすれば、あなたのベースクラスを約soundを知っており、すべての拡張クラスは、抽象プロパティsoundを実装する必要があります。

export abstract class Animal 
{ 
    abstract sound: string; // Only change here, now your code works 
    constructor() { 

    } 

    makeSound() { 
     alert(this.sound); 
    } 
} 

export class Dog extends Animal { 
    public sound: string = "Woof!"; 

    constructor() { 
     super(); 
    } 
} 

const dog = new Dog; 
dog.makeSound(); // Woof! 

抽象的性質はTS 2.0に付属して定義する能力:https://github.com/Microsoft/TypeScript/issues/4669

アップデートを

このアプローチで経験したOP問題は、コメントを見て、抽象的なプロパティが抽象基本クラスのコンストラクタで使用されたことでした。のオブジェクトがインスタンス化された後、最初にプロパティに派生クラスの初期値が割り当てられているので、これは機能しません。

この問題の解決方法は、抽象クラスのコンストラクタ内の抽象プロパティへのアクセスに単純なエラーがある場合です。

+0

アレックス、私は抽象的なキーワードのアプローチを使用してみたとき、私は私の質問で述べたように、サウンドは '未定義'だったので、拡張クラスから値を読み取っていませんでした。私はこれをもう一度試してみましょう、そしてすぐにあなたに知らせてください。編集:うん、 'console.log(this.sound)'を実行すると、 'undefined'が出力されます。私はTypescript '2.1.4'を使用しています。 – Aris

+0

@IcarusCockssonはここでうまくいきます:http://plnkr.co/edit/wRwff7MrFazrjYQHKmFI?p=preview –

+0

@JBNizet @Alex Weird、それは私のためには機能しません。私はあなたが見たいと思ったら私のリポジトリにコミットを押した:https://github.com/Aristona/Phaser.Adventure-Capitalist/tree/master/src/Shop - これは抽象クラスであり、50-55行目はここで抽象プロパティを定義します。ショップフォルダ内のすべてのクラスがショップを拡張し、それらのプロパティを定義します。私がそれを実行すると、それらのすべてが「未定義」になります。 (Shop.tsの50行目と55行目の間のすべて)。何か案は? – Aris

1

はあなたの2つのクラスを定義する必要があります方法は次のとおりです。

export abstract class Animal { 

    protected constructor(public sound: string) { 
    } 

    makeSound() { 
    alert(this.sound); 
    } 
} 

export class Dog extends Animal { 
    constructor() { 
    super('woof'); 
    } 
} 

はAnimalクラスにプロパティを置くすべての動物が音を持っているコンパイラに指示します。サウンドをスーパークラスコンストラクタの引数として置くと、インスタンスを構築するときに、すべてのサブクラスでサウンドを指定する必要があることが明らかになります。

他のバリエーションもありますが、スーパークラスがsoundプロパティまたはgetSound()メソッドにアクセスする必要がある場合、このプロパティ/メソッドは基本クラスに存在する必要があります。

1

エラーメッセージは正確に正しいです:AにはBに存在するため、propは存在しません。あなたはJavaScriptから来ている可能性があります。 TypeScriptとJavaScriptの主な違いは、TypeScriptが強く型付けされ、JavaScriptが弱く型付けされていることです。その違いはあなたの思考の変化を必要とします。

JavaScriptのように弱く型付けされた言語では、propAに存在しません。タイプは実行時に解決され、実際のインスタンスにpropがある場合はすべて正常です。静的に(または強く)型付けされた言語では、状況が異なります。コンパイル時に型が強制され、Aにはpropが定義されていないと使用できません。そのため、厳密に型指定された言語では、抽象メンバを定義することができます。基本クラスでアクセシブルにすることができますが、実際に派生クラスでrhemを定義することができます。

not all versions of TypeScript support abstract properties directlyので、この解決策はどのような場合には動作するはずです:いいえ、それはトップダウンが

export abstract class Animal 
{ 
    get sound(): string { return getSound(); } 
    protected abstract getSound(): string; 
    constructor() {} 
    makeSound(): void { 
     console.log(this.sound); 
    } 
} 

export class Dog extends Animal 
{ 
    protected getSound: string { return "Woof!"; } 

    constructor() { 
     super(); 
    } 
} 

const b = new B; 
B.makeSound(); 
+0

get/set構文は必須ですか?また、次の構文は少し奇妙に見えます。 'protected getProp:string {return" Hello world "; } '。なぜ型を文字列として定義するのですか?オブジェクトリテラルをreturnキーワードで置き換えるのはなぜですか? o_O – Aris

+0

@IcarusCocksson: 'getProp'はメソッドであり、プロパティではありません。少なくとも初期のTypeScriptは抽象プロパティをサポートしていないため、メソッド呼び出しによるget構文は、したがって、ゲッターを使用して抽象メソッドを呼び出します。 – Sefe

関連する問題