web-dev-qa-db-fra.com

Existe-t-il un équivalent à «scellé» ou «final» dans TypeScript?

J'essaie d'implémenter une méthode dans une super classe qui devrait être disponible pour utilisation, mais non modifiable, dans les sous-classes. Considère ceci:

export abstract class BaseClass {
    universalBehavior(): void {
        doStuff(); // Do some universal stuff the same way in all sub classes
        specializedBehavior(); // Delegate specialized stuff to sub classes
    }

    protected abstract specializedBehavior(): void;
}

Mon intention serait que toute sous-classe de BaseClass soit non seulement libre d'omettre l'implémentation de universalBehavior(), mais ne serait même pas autorisée à fournir une implémentation. N'est-ce pas (encore) possible en TypeScript? Intellisense se plaint lorsque j'omets l'implémentation dans mes sous-classes. Le mieux que je puisse faire, c'est ceci:

export class SubClass extends BaseClass {
    universalBehavior(): void {
        super.universalBehavior();
    }

    specializedBehavior(): void {
        // sub class' implementation
    }
}

Évidemment, cela pose problème car je dois m'assurer qu'aucune sous-classe n'implémente jamais universalBehavior() avec autre chose qu'un appel à super.universalBehavior().

25
bubbleking

Non, au moment d'écrire ces lignes, il n'y en a pas. Il existe une proposition pour un tel mot-clé qui est toujours à l'étude, mais qui peut ou non être implémentée.

Voir:

16
bubbleking

Exemple de piratage d'implémentation de 'méthode scellée' en tant que propriété en lecture seule de type fonction qui génère une erreur de compilation lors d'une tentative de substitution dans une classe étendue:

abstract class BaseClass {
    protected element: JQuery<HTMLElement>;
    constructor(element: JQuery<HTMLElement>) {
        this.element = element;
    }
    readonly public dispose = (): void => {
        this.element.remove();
    }
}

class MyClass extends BaseClass {
    constructor(element: JQuery<HTMLElement>) {
        super(element);
    }
    public dispose(): void { } // Compiler error: "Property 'dispose' in type 'MyClass' is not assignable to the same property in base type 'BaseClass'"
}

TypeScript 2.0 prend en charge les classes "finales" en utilisant un constructeur privé:

class A {
    private constructor(){}
}

class B extends A{} //Cannot extend a class 'A'. Class constructor is marked as private.ts(2675)
8
Asher Garland
// I use this workaround:

export default class CreateHandler extends BaseHandler {
    // final prop used as method
    public readonly create = (blueprint: Blueprint): Response<Record> => {
        return blueprint.create();
    };

    // normal method
    public store(blueprint: Blueprint): Response<Record> {
        return this.response(blueprint.create());
    }
}
0
Qwerty Pnk