Доступ до учасника базового класу


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

Я змінив один рядок коду: попередження в 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

Розділ 4.8 охоплює все, що було записано на сьогоднішній день - це, як правило, "це поведінка", хоча, а не "ось чому".
— Фентон

3
Дякую Стіву Фентону. Я також просто натрапив на подібну дискусію тут: typecript.codeplex.com/discussions/418349 . Здається, це дисбаланс у мові; я здогадуюсь, що рішення було укладено, щоб випромінюваний JavaScript був простим, на відміну від допоміжних методів "навколо", щоб компенсувати відсутність підтримки JavaScript.
— Девід Кукча

1

Ви неправильно використовуєте ключове слово superта 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власного об'єкта . Оскільки ми додали властивість імені на Animal.prototype, буде видано Horee.
  2. Другий журнал виводить this.name, thisключове слово стосується самого об'єкта tom.
  3. Третій журнал реєструється за допомогою moveметоду базового класу Animal. Цей метод викликається методом переміщення класу Horse з синтаксисом super.move(45);. Використовуючи superключове слово в цьому контексті, буде шукати moveметод у ланцюзі прототипу, який знаходиться в прототипі Animal.

Пам'ятайте, що TS все ще використовує прототипи під кришкою, classа extendsключові слова - це лише синтаксичний цукор над прототипним успадкуванням.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.