TS之面向对象

151 阅读3分钟

class

  • 定义类
    class Point {
        x: number
        y: number
        constructor(x = 0, y = 0){
            this.x = x
            this.y = y
        }
        printLocation(): void{
            console.log(`x: ${this.x}, y: ${this.y}`)
        }
    }
    
  • 索引签名
    class Hash {
        [s: string]: unknown
        set(key:string, value: unknown){
            this[key] = value
        }
        get(key:string){
            return this[key]
        }
    }
    

classinterface

  • interface只有成员的类型没有实现
  • class必须同时有成员类的型和实现

constructor

  • 初始化实例参数时使用

    • 在构造函数中定义属性,简化代码
    • 必须加上属性修饰符 publicprotectedprivatereadonly
    class Point {
        constructor(public x = 0, public y = 0){
        }
    }
    

constructor重载

  • 构造函数重载
    class Point {
        x!: number
        y!: number
        // 定义类型
        constructor(x: number, y: number);
        constructor(s:string);
    
       // 实现
       constructor(xs: number | string, y?: number){
           if(typecof xs === 'number' && typecof y === 'number'){
               this.x = xs
               this.y = y
           }else if(typeof xs === 'string){
               const parts = xs.split(',')
               this.x = parseFloat(parts[0])
               this.y = parseFloat(parts[1])
           }
       }
    }
    

实现接口

  • 使用implements
  • 可实现1个或多个接口
    interface Person {
        name: string
        sayHi: (target: Person)=>void
    }
    interface Taggable {
        tags: string
        addTag (tag: string) => void
    }
    
    class User implements Person, Taggable {
        name: string
        tags: string[]
        constructor(name:string, tags: string[]){
            this.name = name
            this.tags = tags
        }
        sayHi(target: Person){
            console.log(target.name)
        }
        addTag(tag: string){
            this.tags.push(tag)
        }
    }
    

实现接口中可选参数

  • 需要在类中声明可选参数
    interface Person {
        name: string
        age?: number
    }
    class User implemnets Person {
        constructors(public name: string) { }
    }
    const u = new User('lihhh')
    // u.age // 报错,类型“User”上不存在属性“age”
    

继承

  • 只能继承一个类
  • 使用 super
class Person {
    constructor(public name: string) { }
    sayHi(){ consoel.log(this.name) }
}

class User extends Person  {
    constructor(public id: number, public name: string) { 
        super(name)
    }
    login(){ consoel.log('login success!') }
}

重写

  • 重写父类中的方法
  • super.method()使用父类的方法
class Person {
    constructor(public name: string) { }
    sayHi(){ consoel.log(this.name) }
}

class User extends Person  {
    constructor(public id: number, public name: string) { 
        super(name)
    }
    // 重写方法
    sayHi(target?: User){
        if(target === undefined){
            super.sayHi() // 使用父类的方法
        }else {
            console.log(`target.name`)
        }
    }
}

使用declare

  • 覆盖父类中的属性
    class Person {
        friend?: Person
        constructor(public name: string, friend?:Person){
            trhis.friend = friend
        }
    }
    class User extends Person {
        declare friend: User
        constructor(public id: number, name: string, friend?: User){
            super(name, friend)
        }
    }
    
    const u1 = new User(1, 'Tom')
    const u2 = new User(2, 'Lihhh', u1)
    

成员可见性

  • public (默认)公共的,类外部可见
  • private 类内可见
  • protected 类及其子类可见
  • #var 真私有属性
    • 类型擦除后 真私有属性还存在
    class Person {
      private id: number;
      #name: string;
      protected age: number;
      public sex: string;
      constructor(id: number, name: string, age: number, sex: string) {
        this.id = id;
        this.#name = name;
        this.age = age;
        this.sex = sex;
      }
    }
    class User extends Person {
      constructor(id: number, name: string, age: number, sex: string) {
        super(id, name, age, sex);
      }
    }
    const p = new Person(1, "lihhh", 18, "男");
    // p.name;
    p.sex;
    

static

  • 通过类名访问
  • 类属性
  • 静态属性
    • 静态属性属于构造函数,不是对象独有,所有对象都可以共享
  • 不能有 static name 与构造函数的内置属性函数“name”冲突。

ststic block

  • 对属性进行初始化,在类创建的时候执行
    • 初始化私有属性
      class Foo {
          static #count = 0
          static { 
              const count loadFormLocalStorage() || 0
              Foo.#count += count
          }
      }
      

类、泛型

  • 类中传入泛型
    class Hash<K, V> {
        map: Map<K, V> = new Map()
        set(key: K, value: V){
            this.map.set(key, vlaue)
        }
        get(key: K){
            return this.map.get(key)
        }
    }
    

abstract

  • 定义抽象类使用 abstract 关键字
    • 抽象类不能直接使用,只能被继承
    • 子类必须实现抽象方法或属性
    • 抽象方法只能被定义不能实现,没有函数体
    • 抽象方法必须在抽象类中声明
    abstract class Person {
      abstract name: string;
      age: number;
      constructor(age: number) {
        this.age = age;
      }
      abstract move(): void;
      getPost() {
        console.log("getPost");
      }
    }
    

类作为参数

  • 将类作为参数(不是类的实例(对象))
class Person{}

function f1(X: typeof Person) { const p = new X() }
// new 代表对象
function f2(X: new ()=> Person) { const p = new X() }