Below is an example code(polymorphic) taken from angular framework using TypeScript syntax,
export abstract class AbstractControlDirective {
...
}
AbstractControlDirective
subtypes
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
subtypes
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 {
...
}
In general, there are many situations, that came across new requirements, to add obvious looking super type in intermediate layers of class hierarchy, that injects breakage in subtypes, unless using some design pattern. Using design pattern can make the class hierarchy less error prone but breaks the hierarchy structure.
To avoid this problem, Can we maintain this hierarchy without using extends
keyword? TypeScript being structural typed...
A class should inherit from a parent (extends
keyword in ES6 classes) if one or more following conditions are satisfied:
parent class has explicit constructor that should be inherited in child class, including class fields and constructor parameter properties (which are syntactic sugar for ES6 class constructor body).
parent class has concrete prototype members (methods and getters/setters) that should present in child class
instances of child class should be identifiable as parent class instances at runtime with child instanceof Parent
parent class has decorators that affect anything of the above
Otherwise inheritance doesn't provide any benefits and results in excessive prototype chain; child class can just implement parent interface (implements
keyword).
AbstractControlDirective
contains concrete members that should be inherited in child classes, so NgControl
extends it:
export abstract class NgControl extends AbstractControlDirective {...}
HttpXsrfTokenExtractor
contains only abstract members, so HttpXsrfCookieExtractor
doesn't need to extend it and just implements it as an interface:
export class HttpXsrfCookieExtractor implements HttpXsrfTokenExtractor {...}