类 Class
传统的js中使用函数和基于原型的继承来创建可复用的组件。ES6开始,能够使用基于类的面向对象的方式,ts也支持基于类的面向对象的方式。
可以理解为模板,通过模板可以实例化对象
面向对象的编程思想
基本示例
class Greeter {
// 声明属性
message: string
// 构造函数:为了将来实例化对象的时候,可以直接对属性的值进行初始化
constructor(message: string) {
this.message = message
}
// 一般方法
sayHello(): string {
return 'Hello' + this.message;
}
}
// 创建类的实例
const greeter = new Greeter('word')
// 调用实例
console.log(greeter.sayHello())
继承
类与类之前的关系,A类继承了B这个类,那么此时A类叫子类(派生类),B类叫基类(超类、父类)
class Person{
// 定义属性
name: string
age: number
gender: string
// 定义构造函数
constructor(name: string="小红", age: number=20, gender: string="女") {
this.name = name;
this.age = age;
this.gender = gender
}
// 定义实例方法
sayHi(str: string){
console.log(`我是${this.name},${str}`)
}
}
class Student extends Person {
constructor(name: string, age: number, gender: string) {
// 调用的是父类中的构造函数,使用的是super
super(name, age, gender);
}
sayHi(){
super.sayHi('里斯')
}
}
const person = new Person('小明', 50, '男')
const stu = new Student(‘晓晓’, 12, ‘女’);
多态
父类型的引用指向子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为
class Animal {
name: string
constructor(name: string) {
this.name = name
}
run(distance: number){
console.log(`跑了${distance} 米这么远的距离`, this.name)
}
}
class Dog extends Animal {
constructor(name: string) {
super(name)
}
run(distance: number = 5){
console.log(`跑了${distance} 米这么远的距离`, this.name)
}
}
class Pig extends Animal {
constructor(name: string) {
super(name)
}
run(distance: number = 10){
console.log(`跑了${distance} 米这么远的距离`, this.name)
}
}
// 实例化子类对象
const dog: Animal = new Dog('小灰')
dog.run() // 5, 小灰
// 实例化子类对象
const pig: Animal = new Pig('佩奇')
pig.run() // 10, 佩琦
公共,私有与受保护的修饰符(public/private/protected)
描述类中的成员(属性,构造函数,方法)的可访问性,默认为public。
// 属性修饰
class Animal {
// private name: string //私有属性,外部无法访问,子类也无法访问
// public name: string //公共属性,任何位置都可以访问
protected name: string //受保护的属性,外部无法访问,子类中可以访问
constructor(name: string) {
this.name = name
}
run(distance: number){
console.log(`跑了${distance} 米这么远的距离`, this.name)
}
}
// 构造函数参数修饰
class Person {
// 修饰后name参数称为参数属性,Person中就存在一个公共name的属性成员,private和protected一致
constructor(public name: string='xxx') {
this.name = name
}
}
readonly修饰符
一个关键字,对类中的属性成员进行修饰。
// 属性修饰,修饰后该属性成员不能被外部随意修改。初始化及构造函数中可以修改。
class Person {
readonly name: string
constructor(name: string='xxx') {
this.name = name
}
sayHi() {
console.log('哈利阿斯哟', this.name)
}
}
//构造函数参数修饰,该属性成员不能被外部随意修改
class Person {
// 修饰后name参数称为参数属性,Person中就存在一个name的属性成员
constructor(readonly name: string='xxx') {
this.name = name
}
}
存取器
支持通过getter/setter来劫持对象成员的访问。
class Person {
firstName: string = 'A'
lastName: string = 'B'
//负责读取
get fullName() {
return this.firstName + '-' + this.lastName
}
//负责设置
set fullName(val: string) {
let names = val.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
const per = new Person();
per.fullName = 'E-F'
console.log(per.firstName) // E
静态成员
在类中通过static修饰的属性或者方法,通过类名.来调用
class Person {
static name: string = '小红'
constructor(name: string) {
this.name = name // error 构造函数不能通过static进行修饰
}
sayHi() {
console.log('hello')
}
}
console.log(Person.name) // 小红
console.log(Person.sayHi()) // hello
抽象类
抽象方法不能有任何具体内容的实现。做为其他派生类的基类使用,不能被实例化。通过abstract关键字定义抽象类和在抽象内部定义抽象方法。为了让子类进行实例化及实现内部抽象方法。
抽象类的作用就是为子类存在的。
abstract class Animal{
// 抽象类
abstract eat()
// 实例方法
sayHi() {
console.log(‘hello')
}
}
class Dog extends Animal {
// 重新实现抽象类中的方法,是Dong类的实例方法
eat() {
console.log('趴着吃')
}
}