TS中的类(class)

类(class): 定义了一切事物的抽象特点(属性和方法)
对象(object): 类的实例(通过 new 来生成)
面向对象特点: 封装,继承,多态

  • 封装: 将操作数据的细节隐藏起来,只暴露接口, 调用者只需要通过接口来访问对象
  • 继承: 子类继承父类, 子类除了拥有父类的特性外还可以拥有更加具体的特性
  • 多态: 同一个方法可以有不同的响应(猫和狗都继承自动物类,但是他们叫声各有不同)

封装

抽象一个动物类, 拥有名字属性和奔跑的动作,创建一个基本类 基类(动物类)

// 创建基本类 基类
class Animal {
	// 属性
	name: string 
	// 构造函数
	constructor(name: string) {
		this.name = name
	}
	// 方法 奔跑
	run(){
		return `${this.name} runing`
	}
}
// 实例化类
const snake = new Animal('lily')
console.log(snake.name)
console.log(snake.run())

继承

创建一个狗类继承自动物类

// 延用上面的 Animal 类
class Dog extends Animal {
	// 实现了一个方法 -- 叫
	bark() {
		return `${this.name} is barking`
	}
}
const xiaobao = new Dog('小宝')
xiaobao.name
xiaobao.run()
xiaobao.bark()

多态(方法重写)

方法重写是多态一种表现形式,类似的还有方法的重载 和 接口的定义

// 延用上面的 Animal 类
class Cat extends Animal {
	// 重写构造函数,在子类的构造函数中必须调用 super() 方法
	constructor (name) {
		super(name)
		console.log(this.name)
	}
	// 重写run方法 通过 super 关键字调用父类方法或属性
	run () {
		return `Meow, ${super.run()}`
	}
}
// 实例化 Cat 方法
const maomao = new Cat('毛毛')
console.log(maomao.run())

修饰符

作用: 对类的属性和方法提供权限控制

  • public: 公有的可以在任何地方可以被访问和修改(类中属性和方法默认为publish)
  • private: 私有的仅在当前类可访问和修改
  • protected: 仅当前类与子类(继承类)可以访问和修改
  • readonly: 只读修饰符, 仅可访问不可修改

public 修饰符的使用

// 延用上面的 Animal 类
class Animal {
	// public 修饰符,也可以不加, 属性与方法默认就是 public
	public name: string 
	// 构造函数
	constructor(name: string) {
		this.name = name
	}
	// 方法 奔跑
	run(){
		return `${this.name} runing`
	}
}
// 实例化类
const snake = new Animal('lily')
console.log(snake.name) // => lily
// 把 name 属性修改为 lucy
snake.name = 'lucy'
console.log(snake.name) // => lucy

private 修饰符的使用

class Animal {
	/* 私有的仅在当前类可访问和修改 */
	private name: string  
	// 构造函数
	constructor(name: string) {
		this.name = name
	}
	// 方法 奔跑
	run(){
		return `${this.name} runing`
	}
}
// 实例化类
const snake = new Animal('lily')
console.log(snake.name) // 报错 私有的只能在 Animal 类中访问和更改
// 把 name 属性修改为 lucy
snake.name = 'lucy' // 报错 私有的....
console.log(snake.name) // => 报错 私有的....

protected 修饰符的使用

class Animal {
	/* protected 仅当前类与子类(继承类)可以访问和修改 */
	protected name: string 
	// 构造函数
	constructor(name: string) {
		this.name = name
	}
	// 方法 奔跑
	run(){
		return `${this.name} runing`
	}
}
// Dog 类继承自 Animal
class Dog extends Animal {
	// 实现了一个方法 -- 叫
	bark() {
		// `子类`可以访问父类的属性 name
		return `${this.name} is barking`
	}
}
const xiaobao = new Dog('小宝')
xiaobao.name
xiaobao.run()
xiaobao.bark()

readonly 的使用与public private protected 用法一样, 被readonly 修饰过的属性,只能读取,不能修改,这里就不演示了

静态属性和静态方法

静态: 不需要实例化类, 可以在类上直接访问或调用的属性和方法
静态属性访问方式 不需要实例化, 通过 类名点属性名或方法名 方式访问
静态属性访问:类名.属性名
静态方法调用:类名.方法名

// 创建基本类 基类
class Animal {
	// 定义只读属性 name
	readonly name: string
	// 定义静态属性
	static categoies: string[] = ['mammal','bird']
	// 定义静态方法
	static isAnimal(a) {
		return a instanceof Animal // 判断 a 是否为 Animal 的实例
	}
	// 构造函数
	constructor(name: string) {
		this.name = name
	}
	// 方法 奔跑
	run(){
		return `${this.name} runing`
	}
}
// 注意! 访问 静态属性和方法不需要实例化

// 访问静态属性 categoies
console.log(Animal.categoies)

// 访问 name 属性
const snake = new Animal('lily')
console.log(snake.name)// 注意 name 是 snake 实例的属性

// 调用静态方法
console.log(Animal.isAnimal(snake)) // 判断 snake 是否为 Animal 的实例

区分两个概念

  • 类实例上的属性和方法
    我们在讨论静态属性和方法之前访问属性和方法,都是必须实例化然后访问
    const snake = new Animal('lily') // 实例化
    console.log(snake.name) // 访问实例的属性
    snake.run() // 调用实例的方法
  • 静态属性和方法
    console.log(Animal.categoies) // 不需要实例化 使用类名直接访问
    Animal.isAnimal(snake) // 不需要实例化, 使用类名直接调用
  • 结论:静态属性和方法的定义与实例的状态没有太大的关系

接口定义

接口定义是对不同类中共性的抽象,实际上也是多态的一种表现形式, 在面向对象中一个类只能继承自另外的类, 有时候不同类之间,会有一些共有的特性,用子类继承父类的方法,很难完成对不同类中共性的抽象
举个列子 有 汽车类 和 手机两个没有任何关联的类, 汽车和手机都有收音机, 对于收音机的开关功能就可以定义一个接口让手机类和汽车类继承过去

  • interface 接口定义
  • implements 接口实现
// 汽车类
class Car {
	switchRadio() {} // 收音机开关功能
}
// 手机类
class Phone {
	switchRadio() {} // 收音机开关功能
}

上面的 Car 类和 Phone 类都有相同的特性,都有 switchRadio 功能, 可以把 switchRadio 提取出来, 如果用父类的方式, 必须为 Car 类和 Phone 找一个共同的父类,感觉很难做到,这时候 可以把共有的特性, 提取成一个 interface 通过 implements 关键字让两个类都去实现它

// 提取 Radio 接口
interface Radio {
	// 定义 switchRadio 方法, 接受boolean类型的形参, 返回值 void
	switchRadio(trigger: boolean): void
}

// 汽车类
class Car implements Radio {
	switchRadio() {} // 收音机开关功能
}
// 手机类
class Phone implements Radio {
	switchRadio() {} // 收音机开关功能
}

现在新增一个功能,检查电量, 这个功能仅手机有,汽车没有, 再定义一个接口 Battery

// 提取 Radio 接口
interface Radio {
	// 定义 switchRadio 方法, 接受boolean类型的形参, 返回值 void
	switchRadio(trigger: boolean): void
}

// 汽车类
class Car implements Radio {
	switchRadio() {} // 收音机开关功能
}

// 实现方式一
interface Battery { 
	checkBattery(); // 检查剩余电量
}
class Phone implements Radio,Battery  { // 实现多个接口的定义时, 用逗号隔开
	switchRadio() {} // 收音机开关功能
	checkBattery() {} // 检查剩余电量
}


// 实现方式二
interface RadioWithBattery extends Radio {
	// 继承 Radio 接口就可以拥有 Radio 的属性方法, 同时还可以定义差异化的属性和方法
	checkBattery(); 
}
// phone 类实现 IBattery 接口定义
class Phone implements RadioWithBattery {
	switchRadio() {} // 收音机开关功能
	checkBattery() {} // 检查剩余电量
}

TS中的泛型

你可能感兴趣的:(typescript,typescript,前端)