TypeScript-TypeScript面向对象

69 阅读4分钟

一、TypeScript类的使用

  • 类的定义
// 使用class关键字定义一个类
class Person {
    // 在类的内部声明类的属性以及对应的类型
    // 如果类型没有声明,那么他们默认是any的
    name!: string
    age: number
    
    // 类可以有自己的构造函数constructor,通过new关键字创建一个实例时,构造函数会被调用
    constructor(name: string, age: number) {
        this.age = age
    }
    
    // 类中可以有自己的函数,定义的函数称之为方法
    running() {
        console.log(this.name + " running")
    }
    eating() {
        console.log(this.name + " eating")
    }
}
  • 类的继承:extends关键字来实现继承,子类中使用super来访问父类
class Student extends Person {
    sno: number
    
    constructor(name: string, age: number, sno: number) {
        super(name, age)
        this.sno = sno
    }
   
    studying() {
        console.log(this.name)
    }
}
  • 类的成员修饰符
    • public:修饰的是在任何地方可见、公有的属性或方法,默认编写的属性就是public的
    • private:修饰的是仅在同一类中可见、私有的属性或方法
    • protected:修饰的是仅在类自身以及子类中可见
  • 只读属性readonly
class Person {
    readonly name: string
    
    constructor(name: string) {
        this.name = name
    }
}
  • getters/setters
class Person {
    private _name: string
    
    set name(newName) {
        this._name = newName
    }
    
    get name() {
        return this._name
    }
    
    constructor(name: string) {
        this.name = name
    }
}
  • 参数属性
    • 把一个构造函数参数转成一个同名同值的类属性,这些被称为参数属性
    • 在构造函数参数前添加一个可见性修饰符 public private protected 或者 readonly 来创建参数属性,最后这些类属性字段也会得到这些修饰符
    class Person {
        constructor(public name: string, private _age: number) {
        }
        set age(newAge) {
            this._age = newAge
        }
        get age() {
            return this._age
        }
    }
    

二、TypeScript中抽象类

  • 在TypeScript中没有具体实现的方法(没有方法体),就是抽象方法
    • 抽象方法,必须存在于抽象类中
    • 抽象类是使用abstract声明的类
  • 抽象类的特点
    • 抽象类是不能被实例的(不能通过new创建)
    • 抽象方法必须被子类实现,否则该类必须是一个抽象类
  • 类本身也可以作为一种数据类型的
abstract class Shape {
    abstract getArea(): number
}
class Circle extends Shape {
    private r: number
    constructor(r: number) {
        super()
        this.r = r
    }
    getArea() {
        return this.r * this.r * 3.14
    }
}
class Rectangle extends Shape {
    private width: number
    private height: number
    constructor(width: number, height: number) {
        super()
        this.width = width
        this.height = height
    }
    getArea() {
        return this.width * this.height
    }
}
const circle = new Circle(10)
const rectangle = new Rectangle(20, 30)
function calcArea(shape: Shape) {
    console.log(shape.getArea())
}
calcArea(circle)
calcArea(rectangle)

三、TypeScript对象类型

  • 对象类型的属性修饰符
    • 对象类型中的每个属性可以说明它的类型、属性是否可选、属性是否只读等信息
    • 可选属性:在属性名后面加上一个?标记表示这个属性是可选的
    • 只读属性:readonly
    interface IPerson {
        name: string
        age?: number
        readonly height: number
    }
    const p: IPerson = {
        name: "why",
        height: 1.88
    }
    
  • 索引签名
    • 有的时候,不能提前知道一个类型里所有的属性的名字,但是知道这些值的特征
    • 这种情况,就可以用一个索引签名来描述可能的值的类型
    • 一个索引签名的属性类型必须是string或者是number
    interface ICollection {
        [index: number]: any
        length: number
    }
    function logCollection(collection: ICollection) {
        for (let i = 0; i < collection.length; i++) {
            console.log(logCollection[i])
        }
    }
    const tuple: [string, number, number] = ["why", 18, 1.88]
    const array: string[] = ["aaa", "bbb", "ccc"]
    logCollection(tuple)
    console.log(array)
    

四、TypeScript接口补充

  • 接口继承
    • 接口和类一样是可以继承的,也是使用extends关键字
    • 接口是支持多继承的(类不支持多继承)
    interface Person {
        name: string
        eating: () => void
    }
    interface Animal {
        running: () => void
    }
    interface Student extends Person, Animal {
        sno: number
    }
    const stu: Student = {
        sno: 110,
        name: "why",
        eating: function() {
            console.log("eating~")
        },
        running: function() {
            console.log("running~")
        }
    }
    
  • 接口的实现
    • 接口定义后,也是可以被类实现的
    • 如果被一个类实现,那么在之后需要传入接口的地方,都可以将这个类传入,这就是面向接口开发
    interface ISwim {
        swimming: () => void
    }
    interface IRun {
        running: () => void
    }
    class Person implements ISwim, IRun {
        swimming() {
            console.log("swimming")
        }
        running() {
            console.log("running")
        }
    }
    function swim(swimmer: ISwim) {
        swimmer.swmming()
    }
    const p = new Person()
    swim(p)
    

五、TypeScript枚举类型

  • 枚举类型是为数不多的TypeScript特有的特性之一
    • 枚举其实就是将一组可能出现的值,一个个列举出来,定义在一个类型中,这个类型就是枚举类型
    • 枚举允许开发者定义一组命名常量,常量可以是数字、字符串类型
    enum Direction {
        LEFT,
        RIGHT,
        TOP,
        BOTTOM
    }
    function turnDirection(direction: Direction) {
        switch (direction) {
            case Direction.LEFT:
                console.log("left~")
                break;
            case Direction.RIGHT:
                console.log("right~")
                break;
            case Direction.TOP:
                console.log("top~")
                break;
            case Direction.BOTTOM:
                console.log("bottom~")
                break;
            default: 
                const myDirection: never = direction
        }
    }
    
  • 枚举类型的值
// 枚举类型默认是有值的,默认值为如下
enum Direction1 {
    LEFT = 0,
    RIGHT = 1,
    TOP = 2,
    BOTTOM = 3
}
// 也可以给枚举其他值,如下从100开始递增
enum Direction2 {
    LEFT = 100,
    RIGHT,
    TOP,
    BOTTOM
}
// 也可以给他们赋值其他类型
enum Direction3 {
    LEFT,
    RIGHT,
    TOP = "TOP",
    BOTTOM = "BOTTOM
}