类(class)
ES6引入了class关键字,我们可以像传统的面向对象语言那样去创建一个类了,TS的类覆盖了ES6的类,同时也引入了其他的特性,那么他们有什么不同呢?
定义一个基本类:
class Dog {
constructor(name: string) {
this.name = name
}
name: string
run() {}
}
let dog = new Dog('wn')
分别打印出原型prototype和实例dog:
console.log(Dog.prototype) // Dog { run: [Function], construtor: [Function] }
console.log(dog) // Dog { name: 'wn' }
可以看出:
ES6和TS的类成员的属性都是实例属性,而不是原型属性,类成员的方法都是实例方法
但是不同的是,在TS中,类实例的属性必须具有初始值或者必须在构造函数中初始化
因此这样也是可以的:
class Dog {
constructor() {}
name: string = 'wn'
run() {}
}
let dog = new Dog('abc')
继承
TS类的继承和ES6类的继承一样,采用关键字extends:
class Husky extends Dog {
constructor (name, color: string) {
super(name)
this.color = color
}
color: string
}
- 需要注意的是super要有,且super一定要在this之前
成员修饰符
TS类的成员修饰符有:
- public
- private
- protected
- readonly
- static
public
类的所有属性默认都是public,含义就是对所有人都是可见的,也可以显示声明:
class Dog {
constructor() {}
public name: string = 'wn'
}
private
私有成员只能在类本身被调用,而不能被类的实例和子类中调用;给constructor定义为private,则该类既不能被示例化,也不能被继承:
class Dog {
private constructor(name: string) {}
name: string
run() {}
}
protected
protected受保护成员,只能在类和子类中访问,而不能在类的实例中访问
基类: constructor定义为proteced,表示这个类只能被继承,不能被实例化
readonly
只读,不能被修改,和实例属性一样,一定要初始化
static
类的静态成员,只能被类(包括子类)调用,而不能被实例调用
除了类的成员可以添加修饰符, constructor的参数也可以添加修饰符,作用是将参数自动变成实例的属性,这样可以省略在类中的定义了:
class Husky extends Dog {
constructor (name: string, public color: string) {
super(name)
this.color = color
}
color: string // 构造函数参数加了public修饰符,这里可以省略了
}
抽象类
ES没有引入抽象类的概念,这是TS相对于ES的扩展,所谓抽象类就是只能被继承,而不能被实例化的类
抽象方法:抽象类中不指定方法的具体实现,明确知道子类可以有其他的实现,就没必要在父类中实现
abstract class Animal {
eat() {
console.log('eat')
}
abstract sleep(): void // 抽象方法
}
抽象类的好处: 抽离出事物的共性,有利于代码的复用和扩展
抽象类也可以实现多态:
多态:
父类定义一个方法不去实现,让继承他的子类去实现,每一个子类有不同的表现,多态属于继承
class Cat extends Animal {
constructor(name: string) {
super()
this.name = name
}
name: string
sleep() {
console.log('cat sleep')
}
}
let cat = new Cat('miaomiao')
class Tiger extends Animal {
sleep() {
console.log('Tiger sleep')
}
}
let tiger = new Tiger()
let animals: Animal[] = [cat, tiger]
animals.forEach(i => { // 每一个子类有不同的表现
i.sleep()
})
链式调用
类的方法中返回this,即可实现链式调用
class WorkFlow {
step1() {
return this;
}
step2() {
return this;
}
}
new WorkFlow().step1().step2()
在继承的时候,this也可以表现出多态,指既可以指向父类也可以指向子类, 保持了父类和子类接口调用的连贯性
class Workflow {
step1() {
return this;
}
step2() {
return this;
}
}
class Myflow extends Workflow {
next() {
return this;
}
}
new Myflow().next().step1().next().step2()