快捷搜索: 长连接 前端 源码 pan

TS中的类、接口、泛型

1、class

class Person {

  // 实例属性【通过对象的实例去访问】
  name: string = "美少女";
  // 类属性(静态属性) ,在属性前加static关键字【直接访问】
  static age: number = 17;
  // 只读属性
  readonly sex:string = "female"


  // 实例方法
  sayHello(){
    console.log(hello)
  }
  // 类方法
  static sayBye(){
    console.log(bye)
  }
}
const pre = new Person()

console.log(pre) //{name: 美少女, sex: female}
console.log(Person.age) //17

console.log(pre.sayHello()) //hello
console.log(Person.sayBye()) //bye

2、constructor构造器

class Animal {
  name: string;
  age: number;

  // constructor构造函数,构造函数会在创建时调用
  constructor(name: string, age: number){
    // 在实例方法中,this就表示当前的实例
    this.name = name 
    this.age = age
  }

  bark(){
    // 谁调用this指向谁
    console.log(this)
  }
}

const dog = new Animal(小狗, 2)
const cat = new Animal(mimi, 3)

console.log(dog) //{name: 小狗, age: 2}
console.log(cat) //{name: mimi, age: 3}

dog.bark() //{name: 小狗, age: 2}
cat.bark() //{name: mimi, age: 3}

3、extends继承

(function (){
  // Animal被称为父类,Dog被称为子类
  class Animal{
    name: string;
    age: number;

    constructor(name: string, age: number){
      this.name = name
      this.age = age
    }

    sayHello(){
      console.log(hello)
    }
  }

  // 使用extends继承关键字,子类会继承父类的属性和方法
  class Dog extends Animal{
    run(){
      console.log(`${this.name}狗跑啦~`)
    }
  }
  class Cat extends Animal{
    // 发生继承时,如果子类中的方法会替换掉父类中的同名方法,这就称为方法的[重写]
    sayHello(){
      console.log(喵呜~~~)
    }
  }

  const dog = new Dog(来福, 5)
  const cat = new Cat(咪咪, 2)
  console.log(dog) //{name: 来福, age: 5}
  dog.run() // 来福狗跑啦~
  dog.sayHello() //hello
  console.log(cat) // name: 咪咪, age: 2}
  cat.sayHello() //喵呜~~~
})()

4、super超类

(function (){
  // Animal被称为父类,Dog被称为子类
  class Animal{
    name: string;

    constructor(name: string){
      this.name = name
    }
  }

  // 使用extends继承关键字,子类会继承父类的属性和方法
  class Dog extends Animal{
    age: number;

    // 如果子类中写了构造函数,那么会将父类中的构造函数覆盖掉,所以需要super关键字完成对父类的引用
    constructor(name: string, age: number){
      super(name); //super代表当前类的父类。
      this.age = age
    }
  }

  const dog = new Dog(来福, 5)
  console.log(dog) //{name: 来福, age: 5}
})()

5、public class

(function(){
  // TS中属性具有三种修饰符:public(默认值),可以在类、子类和对象中修改
  class Person{
    public name: string; //写public或者什么都不写默认都是public
    public age: number;

    constructor(name: string, age: number){
      this.name = name + 父; //【可以在类中修改】
      this.age = age
    }

    sayHello(){
      console.log(`大家好,我是${this.name}`)
    }
  }
  // class语法糖
  // class Person{
  //   // 可以将属性定义在构造函数中
  //   constructor(public name: string, public age: number){
  //   }
  // }

  class Employee extends Person{
    constructor(name: string, age: number){
      super(name,age)
      this.name = name + 子 //【子类中可以修改】
    }
  }

  const p1 = new Person(孙悟空, 28)
  console.log(p1) //Person {name: 孙悟空父, age: 28}
  const p2 = new Employee(小猴子, 18)
  console.log(p2) //{name: 小猴子子, age: 18}
  p2.name = "毛猴" // 【可以通过对象修改】
  console.log(p2) //{name: 毛猴, age: 18}
})()

6、protected class

(function(){
  // TS中属性具有三种修饰符:protected ,可以在类、子类中修改
  class Person{
    protected name: string; 
    protected age: number;

    constructor(name: string, age: number){
      this.name = name + 父; //【可以在类中修改】
      this.age = age
    }

    sayHello(){
      console.log(`大家好,我是${this.name}`)
    }
  }

  class Employee extends Person{
    constructor(name: string, age: number){
      super(name,age)
      this.name = name + 子 //【子类中可以修改】
    }
  }

  const p1 = new Person(孙悟空, 28)
  console.log(p1) //Person {name: 孙悟空父, age: 28}
  const p2 = new Employee(小猴子, 18)
  console.log(p2) //{name: 小猴子子, age: 18}
  // p2.name = "毛猴" 【报错,不能修改】
})()

7、private class

(function(){
  // TS中属性具有三种修饰符:private ,可以在类中修改
  class Person{
    private name: string; //private私有属性
    private age: number;

    constructor(name: string, age: number){
      this.name = name + 父; //【可以在类中修改】
      this.age = age
    }

  }

  class Employee extends Person{
    constructor(name: string, age: number){
      super(name,age)
      // this.name = name + 子 //【报错,不能访问修改】
    }
  }

  const p1 = new Person(孙悟空, 28)
  console.log(p1) //Person {name: 孙悟空父, age: 28}
  const p2 = new Employee(小猴子, 18)
  console.log(p2) //{name: 小猴子子, age: 18}
  // p2.name = "毛猴" 【报错,不能修改】
})()

8、private set get calss

(function(){
  // TS中属性具有三种修饰符:private ,可以在类中修改,
  class Person{
    private _name: string; //private私有属性将导致无法再通过对象修改其中的属性
    private age: number;

    constructor(name: string, age: number){
      this._name = name + 父; //【可以在类中修改】
      this.age = age
    }

    // 想要对象可以修改私有属性,就得向外暴露方法【属性的存取器】
    // 使用方式:对象.getName()
    getName(){
      return this._name
    }
    // 等价于 使用方式:对象.name
    // get name(){
    //   return this._name
    // }
    setName(val: string){
      // 为什么提供修改值还要使用private关键字?体会这里可以对赋值做判断
      if(val) {
        this._name = val
      }
     
    }
  }



  const p1 = new Person(孙悟空, 28)
  console.log(p1) //Person {name: 孙悟空父, age: 28}
  console.log(p1.getName()) //孙悟空父 [对应getName]
  // console.log(p1.name)) //孙悟空父 [对应get name]
  p1.setName(熏悟空)
  console.log(p1.getName()) //熏悟空
})()

9、abstract class

(function (){
  // abstract class 抽象类 
  // 抽象类是专门用来被其他类所继承的类,它只能被其他类所继承不能用来创建实例 也就是不能 const dag  = new Animal("大黄")
  abstract class Animal{
    name: string;

    constructor(name: string){
      this.name = name
    }
    // 抽象方法 使用abstract,没有方法体,抽象方法只能定义在抽象类中,子类必须对抽象方法进行重写
    abstract sayHello(): void
  }

  class Dog extends Animal{

    // 因为是继承了抽象类,所以必须重写抽象类中的方法sayHello
    sayHello(): void {
      console.log(汪汪汪!)
    }
  }

  const dog = new Dog(来福)
  console.log(dog) //{name: 来福}
  dog.sayHello() ///汪汪汪
})()

10、interface接口

/**
 * 接口的作用类似于抽象类,不同点在于接口中的所有方法和属性都是没有实值的,换句话说接口中的所有方法都是抽象方法。
 * 接口主要负责定义一个类的结构,接口可以去限制一个对象的接口,对象只有包含接口中定义的所有属性和方法时才能匹配接口。
 * 同时,可以让一个类去实现接口,实现接口时类中要保护接口中的所有属性。
 */
(function(){
  // 描述一个对象的类型【不可创建重复类型】
  type myType = {
    name: string;
    age: number;
  }

  // 接口用来定义一个类结构,用来定义一个类中应该包含哪些属性和方法,同时接口也可以当作类型声明去使用
  interface myInterface{
    name: string;
    age: number;
  }
  // 定义重复的接口,会将两个接口中的属性加起来
  // 接口中的所有属性都不能有实际的值,【只定义对象接口不考虑实际值,接口中所有的方法都是抽象方法】
  interface myInterface{
    gender: string
    sayHello(): void
  }

  const obj: myInterface = {
    name: 美少女,
    age: 16,
    gender: 女,
    sayHello(){
      console.log(我来啦!)
    }
  }
  console.log(obj) // {name: 美少女, age: 16}

  // 定义类时,可以使类去实现接口、(实现接口就是使类满足接口的要求)
  class MyClass implements myInterface{
    name: string;
    age: number;
    gender: string;
    constructor(name: string, age: number, gender: string){
      this.name = name;
      this.age = age;
      this.gender = gender;
    }
    sayHello(){
      console.log(helloooo)
    }
  }

})()

11、泛型

(() => {

  // 定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时泛型便能够发挥作用。

  //使用any也可以满足,但是any会关闭TS的类型检查,其次这样设置也不能体现出参数和返回值是相同的类型
  // function test1(arg: any): any{
  // 	return arg;
  // }

  // 使用泛型: 参数arg是T类型,且返回值也是T类型,
  function test2<T>(arg: T): T{
    return arg
  }
  console.log(test2(10)) //10
  // 也可以指定类型
  console.log(test2<string>("hello")) //hello

  // 可以同时指定多个泛型,泛型间使用逗号隔开:入参a T类型,b K类型,返回值K类型
  function test3<T, K>(a: T, b: K): K{
    return b;
  }
  console.log(test3<number, string>(10, "hello")) // hello

  // 类中同样可以使用泛型:
  class MyClass<T>{
    // 属性propName 为T类型
    propName: T;
    constructor(propName: T){
      this.propName= propName
    }
  }

  // 也可以对泛型的范围进行约束
  interface MyInter{
    length: number;
  }
  function test<T extends MyInter>(arg: T): number{
    return arg.length
  }
})()
经验分享 程序员 微信小程序 职场和发展