Dostęp do elementu członkowskiego klasy bazowej


118

Zobacz przykład dziedziczenia z placu zabaw w witrynie 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);

Zmieniłem jedną linię kodu: alert w Horse.move(). Chcę uzyskać dostęp super.name, ale to po prostu wraca undefined. IntelliSense sugeruje, że mogę go używać, a TypeScript kompiluje się dobrze, ale nie działa.

Jakieś pomysły?

Odpowiedzi:


179

Przykład roboczy. Uwagi poniżej.

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. Nie musisz ręcznie przypisywać nazwy do zmiennej publicznej. Użycie public namew definicji konstruktora robi to za Ciebie.

  2. Nie musisz dzwonić super(name)z wyspecjalizowanych klas.

  3. Korzystanie z this.nameutworów.

Uwagi dotyczące korzystania z super.

Bardziej szczegółowo omówiono to w sekcji 4.9.2 specyfikacji języka.

Zachowanie klas dziedziczących z Animalnie różni się od zachowania w innych językach. Musisz określić supersłowo kluczowe, aby uniknąć pomyłki między wyspecjalizowaną funkcją a funkcją klasy bazowej. Na przykład, jeśli wywołałeś move()lub this.move()miałbyś do czynienia ze specjalizacją Snakelub Horsefunkcją, więc użycie super.move()jawnie wywołuje funkcję klasy bazowej.

Nie ma pomieszania właściwości, ponieważ są one właściwościami instancji. Nie ma różnicy między super.namea this.name- po prostu jest this.name. W przeciwnym razie możesz utworzyć konia, który miałby różne nazwy w zależności od tego, czy należałeś do klasy specjalistycznej, czy podstawowej.


Świetna odpowiedź i dzięki za odniesienie do specyfikacji języka. Czy znasz jakąkolwiek dokumentację wyjaśniającą, dlaczego, na przykład, metody dostępu do właściwości klasy bazowej nie są zwirtualizowane i dostępne za pośrednictwem zastępowania metod dostępu w klasie pochodnej (tak jak metody)?
— David Cuccia,

Sekcja 4.8 obejmuje wszystko, co zostało zapisane do tej pory - zwykle jest to stwierdzenie „takie jest zachowanie”, a nie „to jest dlaczego”.
— Fenton,

3
Dzięki Steve Fenton. Właśnie natknąłem się na podobną dyskusję tutaj: typescript.codeplex.com/discussions/418349 . Wydaje się, że jest to brak równowagi w języku; Domyślam się, że podjęto decyzję o zachowaniu prostoty emitowanego kodu JavaScript, w przeciwieństwie do „obejścia” metod pomocniczych w celu zrekompensowania braku obsługi JavaScript.
— David Cuccia,

1

Nieprawidłowo używasz słowa kluczowego superi this. Oto przykład ich działania:

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.

Wyjaśnienie:

  1. Pierwsze logi super.nameodnoszą się do łańcucha prototypów obiektu tom, a nie do tomsamego obiektu . Ponieważ dodaliśmy właściwość name do Animal.prototype, zostanie wyprowadzone horseee.
  2. Wyjścia drugiego dziennika this.nameThe thiskluczowe odnosi się do samego obiektu Tom.
  3. Trzeci dziennik jest rejestrowany przy użyciu movemetody klasy bazowej Animal. Ta metoda jest wywoływana z metody move klasy Horse ze składnią super.move(45);. Użycie supersłowa kluczowego w tym kontekście spowoduje wyszukanie movemetody w łańcuchu prototypów, który znajduje się w prototypie Animal.

Pamiętaj, że TS nadal używa prototypów pod maską, classa extendssłowa kluczowe i są po prostu cukrem syntaktycznym zamiast prototypowego dziedziczenia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.