如何在TypeScript中的派生类中进行构造函数重载?

时间:2014-10-02 05:45:18

标签: inheritance constructor typescript overloading extends

假设我有一个'基础'类,如:

class CcDefinition {
  // Some properties here

  constructor (json: string);
  constructor (someVar: number, someOtherVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: string) {
    if (typeof jsonOrSomeVar=== "string") {
      // some JSON wrangling code here
    } else {
      // assign someVar and someOtherVar to the properties
    }
  }
}

我希望能够在支持构造函数重载的同时扩展此基类。例如:

class CcDerived extends CcDefinition {
  // Some additional properties here

  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
    if (typeof jsonOrSomeVar=== "string") {
      super.constructFromJson(jsonOrSomeVar);
    } else {
      super.constructFromDef(someOtherVar, someAdditionalVar);
      // assign someVar to the additional properties of this derived class
    }
  }
}

问题是,Typescript要求'super'关键字在构造函数实现中首先出现(字面上)。具体的构建错误消息是:

  

当一个类包含初始化属性或具有参数属性时,“超'调用必须是构造函数中的第一个语句。”

但是,我需要根据提供给扩展(派生)类的内容确定将传递给'super'的参数(即使用不同的构造函数重载)。你应该假设派生类的构造函数重载可能与super的非常不同。

我正在努力实现的目标是什么?

1 个答案:

答案 0 :(得分:7)

此限制仅适用于派生类中初始化成员属性的情况,因此第一种解决方法是仅声明这些属性,然后在派生中初始化它们类构造函数。

换句话说,你可以改变:

class CcDerived extends CcDefinition {
  y = 10;

  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
    if (typeof jsonOrSomeVar=== "string") {
      super(jsonOrSomeVar);
    } else {
      super(someOtherVar, someAdditionalVar);
    }
  }
}

到此:

class CcDerived extends CcDefinition {
  // Some additional properties here
  y: number;

  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
    this.y = 10;
    if (typeof jsonOrSomeVar=== "string") {
      super(jsonOrSomeVar);
    } else {
      super(someOtherVar, someAdditionalVar);
    }
  }
}

请注意,此处的初始化顺序与其他OOP语言大致相同,您需要注意不要从构造函数等调用虚方法。

如果这太令人反感,请注意限制只是第一个语句是超级调用。你经常可以重构超级电话:

class CcDerived extends CcDefinition {
  constructor (json: string);
  constructor (someVar: boolean, someOtherVar: number, someAdditionalVar: string);
  constructor (jsonOrSomeVar: any, someOtherVar?: number, someAdditionalVar?: string) {
      super(
          typeof jsonOrSomeVar === 'string' ? jsonOrSomeVar : someOtherVar,
          typeof jsonOrSomeVar === 'string' ? undefined : someAdditionalVar); 
  }
}

不是最漂亮的,但它至少在语义上是等同的。这假设您的基类构造函数正在检查undefined(而不是arguments.length)以确定调用了哪个重载。