基本クラスのメンバーにアクセスする


118

TypeScriptサイトの遊び場からの継承の例を参照してください。

class Animal {
  public name;
  constructor(name) {
    this.name = name;
  }
  move(meters) {
    alert(this.name + " moved " + meters + "m.");
  }
}

class Snake extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert("Slithering...");
    super.move(5);
  }
}

class Horse extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert(super.name + " is Galloping...");
    super.move(45);
  }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

コードを1行変更しました:のアラートHorse.move()。そこでアクセスしたいのですがsuper.name、それだけで戻りますundefined。IntelliSenseはそれを使用できることを示唆しており、TypeScriptは正常にコンパイルされますが、機能しません。

何か案は?

回答:


179

実例。以下の注意事項。

class Animal {
    constructor(public name) {
    }

    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    move() {
        alert(this.name + " is Slithering...");
        super.move(5);
    }
}

class Horse extends Animal {
    move() {
        alert(this.name + " is Galloping...");
        super.move(45);
    }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);
  1. 名前をパブリック変数に手動で割り当てる必要はありません。public nameコンストラクター定義で使用すると、これが行われます。

  2. super(name)特別なクラスから呼び出す必要はありません。

  3. this.name作品を使う。

の使用上の注意super。

これについては、言語仕様のセクション4.9.2で詳しく説明しています。

継承クラスAnimalの動作は、他の言語の動作と似ています。super特殊化された関数と基本クラス関数の間の混乱を避けるために、キーワードを指定する必要があります。あなたが呼び出された場合たとえば、move()またはthis.move()あなたが専門に対処されるだろうSnakeか、Horseそう使用して、機能super.move()を明示的基底クラスの関数を呼び出します。

プロパティはインスタンスのプロパティであるため、プロパティの混乱はありません。そこに違いはありませんsuper.nameし、this.name単にそこにあります- this.name。それ以外の場合は、特殊クラスに属しているか、基本クラスに属しているかによって、異なる名前の馬を作成できます。


すばらしい回答です。言語仕様を参照していただきありがとうございます。たとえば、メソッドのように、基本クラスのプロパティアクセサーが仮想化されず、派生クラスのオーバーライドアクセサーを介してアクセスできない理由に関するドキュメントを知っていますか?
— David Cuccia 2014年

セクション4.8は、これまでに記述されたすべてのものをカバーしています。「これが理由」ではなく、「これが動作である」傾向があります。
— フェントン

3
Steve Fentonに感謝します。typescript.codeplex.com/discussions/418349でも、ここで同様のディスカッションに遭遇しました。言語の不均衡のようです。JavaScriptのサポートの欠如を補うための「回避策」ヘルパーメソッドとは対照的に、放出されたJavaScriptをシンプルに保つ決定がなされたと私は推測しています。
— David Cuccia 2014年

1

superand thisキーワードを誤って使用しています。これらがどのように機能するかの例を以下に示します。

class Animal {
    public name: string;
    constructor(name: string) { 
        this.name = name;
    }
    move(meters: number) {
        console.log(this.name + " moved " + meters + "m.");
    }
}

class Horse extends Animal {
    move() {
        console.log(super.name + " is Galloping...");
        console.log(this.name + " is Galloping...");
        super.move(45);
    }
}

var tom: Animal = new Horse("Tommy the Palomino");

Animal.prototype.name = 'horseee'; 

tom.move(34);
// Outputs:

// horseee is Galloping...
// Tommy the Palomino is Galloping...
// Tommy the Palomino moved 45m.

説明:

  1. 最初のログ出力super.name。これは、オブジェクト自体のプロトタイプチェーンではtomなく、オブジェクトのプロトタイプチェーンを指しますtom。にnameプロパティを追加したためAnimal.prototype、horseeeが出力されます。
  2. 2番目のログはを出力しますthis.name。thisキーワードはtomオブジェクト自体を参照します。
  3. 3番目のログはmove、Animal基本クラスのメソッドを使用してログに記録されます。このメソッドは、構文でHorseクラスmoveメソッドから呼び出されますsuper.move(45);。superこのコンテキストでキーワードを使用するmoveと、Animalプロトタイプにあるプロトタイプチェーン上のメソッドが検索されます。

TSは内部でまだプロトタイプを使用してclassおり、extendsキーワードandはプロトタイプの継承に対する単なる構文上の砂糖であることを忘れないでください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.