likes
comments
collection
share

TS 面向对象详解

作者站长头像
站长
· 阅读数 18

此文章作为 TS 对 JS 知识点的补充,详细的面向对象学习可参考:js 面向对象详解

类(class)

  • 定义类

    class 类名 {
      属性名: 类型;
    
    	constructor(参数: 类型) {
        this.属性名 = 参数;
      }
    
    	方法名 () {
        ....
      }
    }
    

构造函数和 this

  • this 指的是当前调用方法的对象。

继承

  • 使用继承后,子类将会拥有父类所有的方法和属性。

  • 通过继承可以将多个类中共有的代码写在一个父类里。

  • 如果在子类中添加了父类相同的方法,则子类方法会覆盖父类的方法。

    class Animal {
      name: string;
      age: number;
      language: string;
      constructor(name: string, age: number, language: string) {
        this.name = name;
        this.age = age;
        this.language = language;
        this.printInfo();
      }
      printInfo () {
        console.log(this.name)
        console.log(this.age)
        console.log(this.language)
      }
    }
    
    class Cat extends Animal {
    
    }
    
    const cat = new Cat('旺财', 3, '喵喵喵');
    

super 关键字

  • 可以理解为当前类的父类。

  • 必须在子类的构造函数中调用一下 super 。

    class Animal {
      name: string;
      age: number;
      language: string;
      constructor(name: string, age: number, language: string) {
        this.name = name;
        this.age = age;
        this.language = language;
        this.printInfo();
      }
      printInfo () {
        console.log(this.name)
        console.log(this.age)
        console.log(this.language)
      }
    }
    
    class Cat extends Animal {
    	super.printInfo();
    }
    
    const cat = new Cat('旺财', 3, '喵喵喵');
    

抽象类

  • 以 abstract 开头的类就是抽象类。
    • 抽象类和其他类区别不大,只是不能用来创建对象。
    • 抽象类就是专门用来被继承的。
  • 定义一个抽象方法:
    • 抽象方法使用 abstract 开头,没有方法体。
    • 抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写。

接口

  • 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法,同时接口也可以当成类型声明去使用。

    class Animal {
      interface myInterface {
        name: string;
        age: number;
      }
    
    	interface myInterface {
        gender: string;
      }
    
    	const obj: myInterface = {
        name: 'aaa',
        age: 11,
        gender: '男'
      }
    }
    
  • 接口可以在定义类的时候去限制类的结构。

    • 接口中的所有的属性都不能有实际的值,接口只定义对象的结构,而不考虑实际值。
    • 在接口中所有的方法都是抽象方法。
    • 定义类时,可以使类去实现一个接口,实现接口就是使类满足接口的要求。
    class Animal {
      interface myInterface {
        name: string;
        sayHello(): void;
      }
    
    	class Myclass implements myInterface {
        name: string;
        constructor(name: string) {
          this.name = name;
        }
        sayHello () {
          console.log('大家好!')
        }
      }
    }
    

属性的封装

  • 在对象中设置的属性可以任意地被修改,会导致对象中的数据会变得非常不安全。
  • TS 可以在属性前添加属性的修饰符。
    • public:修饰的属性可以在任意位置访问(修改),默认值。
    • private:私有属性,只有在类的内部进行访问(修改)。
    • protect:受保护的属性,只能在当前类或者当前类的子类中使用。
  • 通过添加方法使得私有属性被外部访问,称为存取器。
    • getter 方法用来读取属性。
    • setter 属性用来设置属性。
class Person {
  private _name: string;
  private _age: number;
  constructor(name: string, age: number) {
    this._name = name;
    this._age = age;
  }
  // TS 中设置 getter 方法的方式。
  get name () {
    return this._name;
  }
  set name (value: string) {
    this._name = value;
  }
  get age () {
    return this._age;
  }
  set age (value: number) {
    if (value >= 0) {
      this._age = value;
    }
  }
}

const per = new Person('孙悟空', 18);
console.log(per.name);
console.log(per.age);
per.name = '猪八戒';
per.age = 33;
console.log(per.name);
console.log(per.age);
  • 简写:

    class C {
      name: string;
      age: number;
      constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
      }
    }
    
    • 以上可以简写为:
    class C {
      constructor(public name: string, public age: number) {
      }
    }
    

泛型

  • 在定义函数或是类时,如果遇到类型不明确就可以使用泛型。

    • 泛型可以指定多个。
    function fn<T>(a: T): T{
      return a;
    }
    
    fn(10)	// 不指定泛型,TS 可以自动对类型进行判断。
    fn<string>('hello')	// 指定泛型。
    
  • 和接口一起使用。

    • T extends Inter 表示泛型 T 必须是 Inter 实现类(子类)。
    interface Inter {
      length: number;
    }
    
    function fn<T extends Inter>(a: T): number {
      return a.length;
    }