TS学习笔记5:类及成员修饰符

164 阅读3分钟

点击此处访问本文所属专栏

TypeScript完全支持ES6中规定的新特性,因此在TS中可以使用class关键字来做基于类的面向对象编程。利用TS的错误提示,也能帮助理解类及修饰符的作用。

1. 基本使用

定义一个Point类,包含两个公共属性x、y,一个公共方法getPosition。因为没有对这些属性做限制和方法做限制,所以他们默认是public的。

class Point {
    x:number
    y:number
    constructor(x:number, y:number) {
        this.x = x
        this.y = y
    }
    getPosition(){
        return `(${this.x}, ${this.y})`
    }
}
const point = new Point (1,2)
console.log(point.getPosition())   // 1, 2

2. 类的继承

类的继承与js语法一致,使用extends关键字即可继承父类

class Parent {
    public name: string
    constructor(name: string) {
        this.name = name
    }
}

class Child extends Parent {
    constructor(name: string) {
        super(name)
    }
}

3. 类的成员修饰符

3.1 访问修饰符

访问修饰符包括3个,分别是public、private、protected

  • public:表示公共属性及方法,可以在使用类的内部、外部、该类的实例、继承的子类中随意访问。如果未对属性添加访问修饰符,则默认该属性是public的。
  • private:表示私有属性,只能在类内部访问,在类的外部、类的实例、子类中都访问不到私有属性。
  • protected:表示受保护的属性,能在类的内部和子类中访问,不能在类的外部、类的实例中访问。如果用如果用protecetd修饰constructor,则这个类不能再创建实例,只能被子类继承。

3.2 只读属性

使用readonly关键字可以将属性设为只读,之后任何修改该属性的行为都会抛出错误。

3.2 静态属性

使用static关键字将属性设为静态属性,则通过这个类生成的实例不会添加该静态属性,也不会继承这个静态属性, 但直接访问类上的属性可以访问成功。

3.3 可选属性

属性名后添加 ‘?’,则该属性变为可选。

下面的例子演示了部分成员修饰符的用法:

class Inof {
    public name: string
    public age?: number
    private _infoStr: string
    constructor (name: string, age?: number, public sex?: string) {
        this.name = name
        this.age =age
    }
    get infoStr() {
        return `${this.name} : ${this.age}`
    }
    set infoStr(value) {
        console.log(`setter: ${value}`)
        this._infoStr = value
    }
}

4. 抽象类

使用abstract关键字可以创建抽象类,抽象类不能用于创建实例,只能供子类继承

abstract class People {
    constructor (public name: string) {}
    public abstract printName(): void
}

class Man extends People {
    constructor(name: string) {
        super(name)
        this.name = name
    }
    printName(){
        console.log(this.name)
    }
}

上面的例子中,子类Man重新实现了一遍printName方法,因为非抽象类不能实现继承自抽象类的抽象成员,因此Man中是不能调用People中的printName方法的。

5.使用接口检测类的属性

接口检测类不能再使用 : 符号,而是使用 implements 关键字。此时如果此类没有实现该接口则会报错。

interface FoodInterface {
    type: string
}

class FoodClass implements FoodInterface {
    public type: string
}

6. 接口继承类

接口继承类,会继承类的成员及成员类型(包括private和protected修饰的成员),但是不包括它的实现。当继承这个类后,接口只能被这个类或这个子类去实现。

class A {
    protected name: string
}

interface I extends A {}

class B extends A implements I{
    public name: string
}

7.在泛型中使用类

下面是在泛型中使用类的例子。其中new()代表调用类的构造函数,它的类型也就是类在创建实例后的实例的类型。当create方法被调用后,传入的类型就是Infos这个类,返回的结果是Infos这个类创建的实例。当访问实例上的name属性时,因为该属性没有在类中被定义,因此会报错。

const create = <T>(c: new() => T): T => {
    return new c()
}

class Infos {
    public age: number
    constructor(){
        this.age = 18
    }
}

const c = create<Infos> (Infos)
c.name  // error