前言
TypeScript真香系列的内容将参考中文文档,但是文中的例子基本不会和文档中的例子重复,对于一些地方也会深入研究。另外,文中一些例子的结果都是在代码没有错误后编译为JavaScript得到的。如果想实际看看TypeScript编译为JavaScript的代码,可以访问TypeScript的在线编译地址,动手操作,印象更加深刻。
类的基础
TypeScript中的类和ES6中的类十分相似,从下面这个例子就能够看出来了:
class Man{
name: string;
constructor(msg: string) {
this.name= msg;
}
play() {
return "Hello, " + this.name;
}
}
let man = new Man("James");
man.name; //"James"
man.play(); //"Hello, James"
我们在上面声明了一个Man类,类中有三个成员:分别为name属性,构造函数,play方法。
继承
TypeScript中类的继承也和ES6中类似,派生类(子类)可以从基类(父类)中继承属性和方法。
class Man{
name: string;
constructor(msg: string) {
this.name= msg;
}
play() {
return "Hello, " + this.name;
}
}
class Player extends Man {
age: string;
constructor(name: string,age:string) {
super(name)
this.age = age;
}
showAge() {
return this.age;
}
}
let player = new Player("James","35");
player.age; //"35"
player.name; //"James"
player.play(); //"Hello, James"
在上面的代码中,Man类就是我们的基类,Player 类就是我们的派生类。通过关键字extends ,我们就可以实现类的继承。若派生类中包含了构造函数,则必须调用super(),它会执行基类的构造函数。
公共,私有与受保护的修饰符
public
在TypeScript中,成员都是默认标记为public,可以理解为公开,所以我们可以自由的访问程序里面定义的成员。当然我们也可以显式的标记出来:
class Man{
public name: string;
public constructor(msg: string) {
this.name= msg;
}
public play() {
return "Hello, " + this.name;
}
}
private
我们可以把类中的成员标记为private,可以理解为私有的。一旦成员标记标记为private,我们就不能在它的类的外部访问它。
class Man {
private name: string;
constructor(msg: string) {
this.name = msg;
}
}
new Man("James").name; // 错误: 'name' 是私有的.
并且在Man的派生类中也是不能访问的:
class Man {
private name: string;
constructor(msg: string) {
this.name = msg;
}
}
class Player extends Man {
constructor(name: string) {
super(name);
}
}
let player = new Player("James");
player.name; //错误, 'name' 是私有的.
如果想要访问Man类中的name,那么我们可以在Man类中定义一个方法show():
class Man {
private name: string;
constructor(msg: string) {
this.name = msg;
}
show() {
return this.name;
}
}
class Player extends Man {
constructor(name: string) {
super(name);
}
}
let player = new Player("James");
plager.show(); //"James"
我们还可以用下面这个修饰符来进行类似的操作。
protected
protected,可理解为受保护的,和private相似,有一点不同的就是,protected成员可以在派生类中可以访问:
class Man {
protected name: string;
constructor(msg: string) {
this.name = msg;
}
}
class Player extends Man {
constructor(name: string) {
super(name);
this.name = name;
}
show() {
return this.name
}
}
let man = new Man("James");
man.name; //错误, 'name' 是受保护的.
let player = new Player("James");
player.name; //错误, 'name' 是受保护的.
player.show(); // "James"
protected当然也可以标记构造函数。当构造函数被protected标记后,当前类就不能被实例化了,但是可以被派生类继承:
class Man {
protected name: string;
protected constructor(msg: string) {
this.name = msg;
}
}
class Player extends Man {
constructor(name: string) {
super(name);
this.name = name;
}
}
let man = new Man("James"); //错误,Man的构造函数是受保护的
let player = new Player("James");
readonly修饰符
我们可以使用readonly将成员设置为只读,只读属性必须在声明时或构造函数里被初始化。
class Man {
readonly name: string;
constructor(msg: string) {
this.name = msg;
}
}
let man = new Man("James");
man.name = "wade"; //错误,name是只读属性
我们还有另一种写法:
class Man {
constructor(readonly name: string) {
}
}
let man = new Man("James");
对比上面种写法,发现下面这种方式简洁了许多,这是我们使用了参数属性。参数属性可以让我们方便的在一个地方定义并初始化一个成员,而且可以通过给构造函数前面添加一个访问限定符(public,private,protected)来进行声明。如下所示:
//使用前
class Man {
public name:string
constructor(name: string) {
this.name = name
}
}
//使用后
class Man {
constructor(public name: string) {
}
}
存取器
在TypeScript中,我们可以利用存取器来帮助我们有效的控制对对象成员的访问。
首先看没有存取器的版本:
class Man {
public name: string;
constructor(msg: string) {
this.name = msg
}
}
let man = new Man("James");
man.name = "wade";
console.log(man.name); // wade
然后是存取器版本:
class Man {
public _name: string;
constructor(msg: string) {
this._name = msg;
}
get myName(): string{
return this._name;
}
set myName(newName: string) {
this._name = newName;
}
}
let man = new Man("James");
console.log(man.myName); // James
man.myName = "wade";
console.log(man.myName); // wade
这里有两个地方需要注意:一是,存取器要求我们配置时将编译器设置为输出ECMAScript 5或更高的版本;二是,存取器只带get不带set的话,存取器会自动推断为readonly。
静态属性
TypeScript的静态属性和JavaScript中的静态属性是类似的。我们创建的类的静态成员,这些属性是在类的本身而不是在类的实例上:
class Man {
static player: string = "运动员";
show() {
return "我职业:" + Man.player
}
}
let man = new Man();
man.player; //错误,player是静态成员
Man.player; // 运动员
man.show(); // 我职业:运动员
抽象类
TypeScript中的抽象类是提供其他派生类的基类,但是不能直接被实例化。我们可以用abstract关键字来定义抽象类和抽象类中的方法。其用法如下:
abstract class Man {
constructor(public name: string) {
}
show() {
return "我的名字:" + this.name
}
abstract play(type:string): void; //这个方法必须在派生类中实现,不然派生类就会报错
}
class Player extends Man {
constructor(name:string) {
super(name) //派生类中的构造函数必须调用super()
}
play(type:string) {
return "我的职业是" + type;
}
go() {
return "冲冲冲";
}
}
let man: Man; //可以创建一个对抽象类的引用
man = new Man("James"); // 错误,不能创建一个抽象类的实例
man = new Player("Wade"); //可以对一个抽象子类进行进行实例化和赋值
man.go(); //错误,go方法在声明的抽象类中不存在
man.play("basketball"); //"我的职业是basketballer"
参考
https://github.com/zhongsp/Ty...
最后
文中有些地方可能会加入一些自己的理解,若有不准确或错误的地方,欢迎指出~
祝大家新年快乐,阖家辛福!
希望前线的医护人员健健康康,早日打败病毒!
希望大家都健健康康!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。