Typescript之继承应用(学习笔记)

310 阅读2分钟

super的两个应用

用法1:在子类的构造函数中使用 super,就表示用来调用父类构造函数

class animal {
  public gender: string
  public age: number
  public weight: number
  constructor(gender: string, age: number, weight: number) {
    this.gender = gender
    this.age = age
    this.weight = weight
  }

  public sleep() {
    console.log('动物都要睡觉')
  }
}

class rabbit extends animal {
  public name: string
  public type: string

  constructor(name: string, type: string, gender: string, age: number, weight: number) {
    // 关键点
    super(gender, age, weight)
    this.name = name
    this.type = type
  }
}

编译成 JS 源码后 可以看到:就是采用 JS 原型中的借用构造函数来实现的

var _this = _super.call(this, gender, age, weight) || this;

用法2:在子类重写的方法中调用父类同名方法,super.重写的方法

class animal {
  public gender: string
  public age: number
  public weight: number
  constructor(gender: string, age: number, weight: number) {
    this.gender = gender
    this.age = age
    this.weight = weight
  }

  protected sleep() {
    console.log('动物都要睡觉')
  }
}


class rabbit extends animal {
  public name: string
  public type: string

  constructor(name: string, type: string, gender: string, age: number, weight: number) {
    super(gender, age, weight)
    this.name = name
    this.type = type
  }
  // 重写父类方法
  public sleep() {
    super.sleep()
    console.log('兔子在洞穴里睡觉')
  }
}

此外方法重写还有一些要求

  1. 和父类方法同名
  2. 参数和父类相同,如果是引用类型的参数,需要依据具体类型来定义
  3. 父类方法不能是private

源码解析

ts转换成js后:

// 继承方法
var __extends = (this && this.__extends) || (function () {
    // 这个方法是继承父类静态属性和方法
    var extendStatics = function (d, b) {
        /**
         有三种方法可以实现,一种是es6写法,Object.setPrototypeOf
         第二种是d._proto_= b,第三种就是通过for,in循环
        **/ 
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) {  d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        if (typeof b !== "function" && b !== null)
            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
        extendStatics(d, b);
        function __() { this.constructor = d; }
        //这个就是寄生继承,继承父类原型链,有意思的是这个逗号表达式用法,学到了
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        // 等价于
        // if(b) {
        //    _.prototype = b.prototype
        //    d.prototype = new _()
        // }else {
        //    d.prototype = Object.create(b)
        // }
    };
})();
// 父类
var animal = /** @class */ (function () {
    function animal(gender, age, weight) {
        this.gender = gender;
        this.age = age;
        this.weight = weight;
    }
    animal.prototype.sleep = function () {
        console.log('动物都要睡觉');
    };
    return animal;
}());
// 子类
var rabbit = /** @class */ (function (_super) {
    // 先调用继承方法,继承父类      
    __extends(rabbit, _super);
    function rabbit(name, type, gender, age, weight) {
        // 借用父类构造函数,进行赋值
        var _this = _super.call(this, gender, age, weight) || this;
        _this.name = name;
        _this.type = type;
        return _this;
    }
    return rabbit;
}(animal));