总体来讲,TS中的类覆盖了ES6中的类,并引入了一些新的特性。
类的基本实现
class Dog{
constructor(name:string){ //构造函数的返回值会自动推断为Dog,也就是这个类的本身
this.name=name; //初始化实例属性
}
name:string;
run(){} //默认返回值是void
}
这里我们需要注意几个问题:
- 不管在TS还是在ES中,类成员的属性都是实例属性,而不是原型属性
- 类成员的方法都是原型方法
- 与ES中不同的是,实例的属性必须具有初始值或者在构造函数中被初始化
类的继承
我们来定义一个Dog的子类Husk
class Husk extends Dog{
constructor (name:string,color:string){
super(name); //代表父类的实例
this.color=color; //this一定要在super调用之后在调用
}
color:string; //给子类添加一个color属性
}
类的成员修饰符
这是TS对ES的一种扩展
- public:公有成员,类的所有属性默认都是public,对所有人都是可见的(当然我们也可以显示的声明)
class Dog{ constructor(name:string){ this.name=name; } public name:string; run(){} }
-
private:私有成员,只能在类的本身被调用,而不能被类的实例调用,也不能被子类调用(不能被继承)
class Dog{ constructor(name:string){ this.name=name; } public name:string; private pri(){} //私有成员 run(){ this.pri() } } let dog=new Dog('wang'); dog.pri() //属性“pri”为私有属性,只能在类“Dog”中访问。
-
protected:受保护成员,只能在类和子类中访问,不能在实例中访问
class Dog{ constructor(name:string){ this.name=name; } name:string; protected pro(){} } let dog=new Dog('wang'); dog.pro() //属性“pro”受保护,只能在类“Dog”及其子类中访问。
我们也可以将构造函数声明为protected ,但是这相当鸡肋,表示不能被实例化,只能被继承
-
readonly:只读属性
readonly legs:number=6; //只读属性
-
static:类的静态成员 (只能通过类名来调用)
static food:string='bons'
类的静态成员也是可以被继承的
构造函数的参数也可以添加修饰符,它的作用就是将参数自动变成实例的属性,这样我们就能够省略在类中定义了
class Dog{
constructor(public name:string){
this.name=name;
}
// name:string;
}
抽象类
抽象类是TS对ES的又一次扩展,不能被创建实例,只能被继承( 通过 abstract 关键字)
//创建一个抽象类
abstract class Animal{ //抽象类
eat(){
console.log('eat'); //我们可以在抽象类中定义一个方法,它可以有具体的实现,可以实现逻辑(方法)的复用
}
abstract sleep():void //抽象方法,不指定方法的具体实现(明确知道子类可以有其他的实现,没必要在父类中实现)
}
// let animal=new Animal() //无法创建抽象类的实例。
class Dog extends Animal{
constructor(name:string){
super();
this.name=name;
}
name:string
run(){}
sleep(){
console.log('sleep...')
}
}
let dog= new Dog('huas')
dog.eat() //eat
抽象类的好处:可以抽离出事物的一些共性,有利于代码的复用和扩展
类和接口的关系
- 类类型接口(一个接口可以约束类成员有哪些属性以及它们的类型)
//定义一个Human接口 interface Human{ name:string; eat():void; } // 类实现接口的时候,必须实现接口中声明的所有属性 class Asian implements Human{ constructor(name:string){ this.name=name; } name:string; eat(){}; sleep(){} }
注意:接口只能约束类的公有成员
- 接口的继承
interface Man extends Human{ run():void; } interface Child{ cry():void; } interface Boy extends Man,Child { } let boy:Boy={ name:"", run(){}, eat(){}, cry(){} }
一个接口可以继承多个接口;接口的继承可以抽离出可重用的接口,也可以将多个接口合并成一个接口
-
接口来继承类
class Auto{ state=1; } interface Autoface extends Auto{ } class C implements Autoface{ state=1; } class Bus extends Auto implements Autoface{ }
接口在抽离类的成员的时候,不仅抽离了公共成员,而且抽离了私有成员,受保护成员