打字稿手册中的继承示例
inheritance example from typescript manual
阅读 typescript manual 中的示例:
class Animal {
name:string;
constructor(theName: string) { this.name = theName; }
move(meters: number = 0) {
alert(this.name + " moved " + meters + "m.");
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(meters = 5) {
alert("Slithering...");
super.move(meters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(meters = 45) {
alert("Galloping...");
super.move(meters);
}
}
var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
问题是关于行 var tom: Animal = new Horse("Tommy the Palomino");
:
据我了解,tom
是具有 Horse
属性的 Animal
。那正确吗?
这样做有什么意义呢?不声明为 var tom: Horse = ...
?
只有一个版本让他有机会 degrade/change/evolve 成为 Snake
或任何其他 Animal
。我说的对吗?
...或者这只是一个错字?
在上面的例子中,Animal
是一个superclass(也叫base class 或 Horse
和 Snake
的 父级 class)。相应地,Horse
和Snake
是subclasses(派生classes) Animal
.
当您声明子class时:
class Snake extends Animal
...
class Horse extends Animal
您是在告诉编译器任何每个 Snake
和每个 Horse
实际上也是一个 Animal
。这使得 Animal
成为程序 "world" 中更广泛的类别。 Snake
和 Horse
将 继承 Animal
的属性,但他们可以更改它们(and/or 添加一些他们自己的)变得更 专业化 .
tom
的声明告诉编译器该变量将接受任何 Animal
。正如我们之前看到的,Horse
是一个 Animal
,所以编译器让它通过。
因此,他们说明了这样一个事实,即无论何时在任何表达式中期望 superclass 的成员,其任何 subclasses 的成员都是可接受的。这称为 协方差.
从最字面的意义上讲,没有进化或退化。行
tom: Animal = new Horse("Tommy the Palomino");
首先导致创建一个新的 Horse
对象。然后将对象分配给变量 tom
,但此分配 不会 更改对象的属性。如果你 运行 这个例子,你会看到调用 horse.move()
实际上调用了方法 move
的 Horse
版本,它会报告 "Tommy the Palomino moved 45m"。
将 Horse
分配给 Animal
的唯一可辨别的副作用是变量,作为最通用的类型,不知道 [=13= 的任何特殊属性].它只知道所有 Animal
的共同点。假设 Horse
是这样声明的:
class Horse extends Animal {
constructor(name: string) { super(name); }
move(meters = 45) {
//...
}
swat_fly() { /* ... */ }
}
您将无法拨打 tom.swat_fly()
。如果你愿意,你要么需要类型转换 tom
(像这样:(<Horse>tom).swat_fly()
),要么将其声明为 Horse
而不是 Animal
。但是我重申:对象的属性没有改成superclass的.
所以不,这不是打字错误:)
阅读 typescript manual 中的示例:
class Animal {
name:string;
constructor(theName: string) { this.name = theName; }
move(meters: number = 0) {
alert(this.name + " moved " + meters + "m.");
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(meters = 5) {
alert("Slithering...");
super.move(meters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(meters = 45) {
alert("Galloping...");
super.move(meters);
}
}
var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
问题是关于行 var tom: Animal = new Horse("Tommy the Palomino");
:
据我了解,
tom
是具有Horse
属性的Animal
。那正确吗?这样做有什么意义呢?不声明为
var tom: Horse = ...
?只有一个版本让他有机会 degrade/change/evolve 成为
Snake
或任何其他Animal
。我说的对吗?...或者这只是一个错字?
在上面的例子中,Animal
是一个superclass(也叫base class 或 Horse
和 Snake
的 父级 class)。相应地,Horse
和Snake
是subclasses(派生classes) Animal
.
当您声明子class时:
class Snake extends Animal
...
class Horse extends Animal
您是在告诉编译器任何每个 Snake
和每个 Horse
实际上也是一个 Animal
。这使得 Animal
成为程序 "world" 中更广泛的类别。 Snake
和 Horse
将 继承 Animal
的属性,但他们可以更改它们(and/or 添加一些他们自己的)变得更 专业化 .
tom
的声明告诉编译器该变量将接受任何Animal
。正如我们之前看到的,Horse
是一个Animal
,所以编译器让它通过。因此,他们说明了这样一个事实,即无论何时在任何表达式中期望 superclass 的成员,其任何 subclasses 的成员都是可接受的。这称为 协方差.
从最字面的意义上讲,没有进化或退化。行
tom: Animal = new Horse("Tommy the Palomino");
首先导致创建一个新的
Horse
对象。然后将对象分配给变量tom
,但此分配 不会 更改对象的属性。如果你 运行 这个例子,你会看到调用horse.move()
实际上调用了方法move
的Horse
版本,它会报告 "Tommy the Palomino moved 45m"。将
Horse
分配给Animal
的唯一可辨别的副作用是变量,作为最通用的类型,不知道 [=13= 的任何特殊属性].它只知道所有Animal
的共同点。假设Horse
是这样声明的:class Horse extends Animal { constructor(name: string) { super(name); } move(meters = 45) { //... } swat_fly() { /* ... */ } }
您将无法拨打
tom.swat_fly()
。如果你愿意,你要么需要类型转换tom
(像这样:(<Horse>tom).swat_fly()
),要么将其声明为Horse
而不是Animal
。但是我重申:对象的属性没有改成superclass的.所以不,这不是打字错误:)