TypeScript真香系列-类

前言

TypeScript真香系列的内容将参考中文文档,可是文中的例子基本不会和文档中的例子重复,对于一些地方也会深刻研究。另外,文中一些例子的结果都是在代码没有错误后编译为JavaScript获得的。若是想实际看看TypeScript编译为JavaScript的代码,能够访问TypeScript的在线编译地址,动手操做,印象更加深入。javascript

类的基础

TypeScript中的类和ES6中的类十分类似,从下面这个例子就可以看出来了:java

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方法。git

继承

TypeScript中类的继承也和ES6中相似,派生类(子类)能够从基类(父类)中继承属性和方法。github

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(),它会执行基类的构造函数。typescript

公共,私有与受保护的修饰符

public

在TypeScript中,成员都是默认标记为public,能够理解为公开,因此咱们能够自由的访问程序里面定义的成员。固然咱们也能够显式的标记出来:函数

class Man{
    public name: string;
    public constructor(msg: string) {
        this.name= msg;
    }
    public play() {
        return "Hello, " + this.name;
    }
}
复制代码

private

咱们能够把类中的成员标记为private,能够理解为私有的。一旦成员标记标记为private,咱们就不能在它的类的外部访问它。ui

class Man {
    private name: string;
    constructor(msg: string) {
        this.name = msg;
    }
}

new Man("James").name; // 错误: 'name' 是私有的.
复制代码

而且在Man的派生类中也是不能访问的:this

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():spa

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"
复制代码

咱们还能够用下面这个修饰符来进行相似的操做。code

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"
复制代码

参考

github.com/zhongsp/Typ…

最后

文中有些地方可能会加入一些本身的理解,如有不许确或错误的地方,欢迎指出~ 祝你们新年快乐,阖家辛福! 但愿前线的医护人员健健康康,早日战胜病毒! 但愿你们都健健康康!

相关文章
相关标签/搜索