Доступ к члену базового класса
Посмотрите пример наследования с игровой площадки на сайте 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 компилируется нормально, но это не работает.
Есть идеи?
Ответы
Ответ 1
Рабочий пример. Примечания ниже.
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);
-
Вам не нужно вручную присваивать имя публичной переменной. Использование public name
в определении конструктора сделает это за вас.
-
Вам не нужно вызывать super(name)
из специализированных классов.
-
Использование this.name
работает.
Заметки по использованию super
.
Это более подробно описано в разделе 4.9.2 спецификации языка.
Поведение классов, наследуемых от Animal
, не отличается от поведения в других языках. Вам необходимо указать ключевое слово super
, чтобы избежать путаницы между специализированной функцией и функцией базового класса. Например, если вы вызвали move()
или this.move()
вы бы имели дело со специализированной функцией Snake
или Horse
, поэтому использование super.move()
явно вызывает функцию базового класса.
Не существует путаницы свойств, так как они являются свойствами экземпляра. Между super.name
и this.name
нет никакой разницы - есть просто this.name
. В противном случае вы могли бы создать Лошадь с разными именами в зависимости от того, были ли вы в специализированном классе или в базовом классе.
Ответ 2
Вы неправильно используете 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.
Объяснение:
- Первый лог выводит
super.name
, это относится к цепочке прототипов объекта tom
, а не объекта tom
Self. Поскольку мы добавили свойство name в Animal.prototype
, будет Animal.prototype
horseee. - Второй журнал выводит
this.name
, ключевое слово this
относится к самому объекту Tom. - Третий журнал регистрируется с помощью метода
move
базового класса Animal. Этот метод вызывается из метода перемещения класса Horse с синтаксисом super.move(45);
, Использование ключевого слова super
в этом контексте будет искать метод move
в цепочке прототипов, который находится в прототипе Animal.
Помните, что TS все еще использует прототипы под капотом и class
и extends
ключевые слова как синтаксический сахар по сравнению с прототипным наследованием.