结构类型和多态性——添加超类型

Structural typing and Polymorphism - Adding super types

下面是使用 TypeScript 语法取自 angular framework 的示例代码(多态),

export abstract class AbstractControlDirective {
   ...
}

AbstractControlDirective 亚型

export abstract class NgControl extends AbstractControlDirective {
     ...
}
export abstract class ControlContainer extends AbstractControlDirective {
   ...
}
export declare abstract class ControlContainer extends AbstractControlDirective {
  ...
}
export declare abstract class NgControl extends AbstractControlDirective {
    ...
}

NgControl 亚型

export class NgModel extends NgControl implements OnChanges, OnDestroy {
   ...
}

export class FormControlDirective extends NgControl implements OnChanges {
    ....
}

export class FormControlName extends NgControl implements OnChanges, OnDestroy {
   ...
}

export declare class FormControlDirective extends NgControl implements OnChanges {
    ...
}

export declare class FormControlName extends NgControl implements OnChanges, OnDestroy {
   ...
}

export declare class NgModel extends NgControl implements OnChanges, OnDestroy {
   ...
}

一般来说,有很多情况会遇到新的需求,在 class 层次结构的中间层添加看起来很明显的超类型,这会在子类型中注入破坏,除非使用某种设计模式。使用设计模式可以使 class 层次结构不易出错,但会破坏层次结构。


为了避免这个问题,我们可以在不使用 extends 关键字的情况下维护这个层次结构吗?正在对 TypeScript 进行结构类型化...

如果满足以下一个或多个条件,class 应该从父项(extends ES6 classes 中的关键字)继承:

  • parent class 有明确的构造函数,应该在子 class 中继承,包括 class 字段和构造函数参数属性(这是 ES6 [的语法糖 class 构造函数体).

  • parent class 有具体的原型成员(方法和 getters/setters)应该出现在 child class

  • 子 class 的实例在运行时应可识别为父 class 实例 child instanceof Parent

  • parent class 具有影响上述任何内容的装饰器

否则继承不会提供任何好处并导致过多的原型链;子 class 可以只实现父接口(implements 关键字)。

AbstractControlDirective contains concrete members that should be inherited in child classes, so NgControl 扩展它:

export abstract class NgControl extends AbstractControlDirective {...}

HttpXsrfTokenExtractor contains only abstract members, so HttpXsrfCookieExtractor不需要扩展它,只是将它实现为一个接口:

export class HttpXsrfCookieExtractor implements HttpXsrfTokenExtractor {...}