继承和成员修饰符
类的基本实现
定义一个Dog类,与ES不同的是,我们为成员属性添加了类型注解,也为构造函数的参数增加了类型注解。
class Dog {
constructor(name: string) {
this.name = name
}
name: string
run() {}
}
需要注意的是:
(1)无论是在ES还是ts中,类成员的属性都是实例属性,而不是原型属性;类成员的方法也都是实例方法。对比可见:
console.log(Dog.prototype) // {run: ƒ, constructor: ƒ}
let dog = new Dog('wangwang')
console.log(dog) // Dog {name: "wangwang"}
(2)与ES不同的是,实例的属性必须具有初始值,或者在构造函数中被初始化。 以下√的三种方式均是可以的:
class Dog {
constructor(name: string) {
// this.name = name √
}
// name: string = 'dog' √
// name?: string = 'dog' √
run() {}
}
类的继承(用extends关键字)
class Husky extends Dog {
constructor(name: string, color: string) {
super(name)
this.color = color
}
color: string
}
需要注意的是:
(1)派生类的构造函数必须包含‘super’调用,而且参数必须包含父类的参数。
(2)新添加的属性要初始化,一般在constructor中,而且用到的this必须在super调用后才能调用。
类的成员修饰符(这是ts对ES的扩展)
公有成员:对所有人都是可见的,格式public+属性/函数名
私有成员,也能在类的本身被调用,而不能被类的实例调用,也不能被子类调用,格式private+属性/函数名
class Dog {
constructor(name: string) {
this.name = name
}
name: string
run() {}
private pri() {}
}
let dog = new Dog('wangwang')
dog.pri() ❌
class Husky extends Dog {
constructor(name: string) {
super(name)
this.pri() ❌
}
}
PS:
也可以给构造函数加上私有成员属性,作用是类既不能被实例化,也不能被继承,都会提示错误。
class Dog {
private constructor(name: string) {
this.name = name
}
name: string
}
let dog = new Dog('wangwang') ❌
class Husky extends Dog { } ❌
受保护成员,只能在类或子类中访问,而不能在类的实例中访问,格式protected+属性/函数名。
class Dog {
constructor(name: string) {
this.name = name
}
name: string
protected pro() {}
}
let dog = new Dog('wangwang')
dog.pro() ❌
class Husky extends Dog {
constructor(name: string) {
super(name)
this.pro() ✔
}
}
PS:
构造函数也能被声明为protected,作用是这个类不能被实例化,只能被继承,就相当于声明了一个基类。
class Dog {
protected constructor(name: string) {
this.name = name
}
name: string
}
let dog = new Dog('wangwang') // ❌
class Husky extends Dog {
......
}
只读属性:不可以被更改,切记它跟实例属性一样,一定要被初始化。
class Dog {
constructor(name: string) {
this.name = name
}
name: string
readonly legs: number = 4
}
构造函数的参数也可以添加修饰符,它的作用是将参数自动变成了实例的属性,这样就能省略在类中的定义了。
class Husky extends Dog {
constructor(name: string, public color: string) {
super(name)
this.color = color
}
// color: string
}
静态成员:只能通过类名来调用,而不能通过子类调用,它是可以被继承的,格式static修饰符+属性名。
class Dog {
constructor(name: string) {
this.name = name
}
name: string
static food: string = 'bones'
}
let dog = new Dog('wangwang')
console.log(Dog.food) // ✔
// console.log(dog.food) ❌
class Husky extends Dog {
constructor(name: string, public color: string) {
super(name)
this.color = color
}
}
console.log(Husky.food) // ✔