类(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
修饰符的使用
// 延用上面的 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中的泛型