Vyhledávání na webu

Vlastnosti třídy v Typescriptu nejsou inicializovány


Mám následující třídu:

export abstract class LayerStyle {
    protected configuration: { [key: string]: string };
    protected style: ol.style.Style[];

    constructor(config: { [key: string]: string }) {
        this.configuration = config;
        this.createStyle();
    }

    protected abstract createStyle(): void;

    getStyle() {
        return this.style;
    }
}

A jeho dětská třída:

import { LayerStyle } from './LayerStyle';

export class PointStyle extends LayerStyle {
    //default values
    FILL_COLOR = 'rgba(255,255,255,0.4)';
    STROKE_COLOR = '#3399CC';
    STROKE_WIDTH = 1.25;
    RADIUS = 5;

    createStyle() {
        let fillColor = this.FILL_COLOR;
        let strokeColor = this.STROKE_COLOR;
        let strokeWidth = this.STROKE_WIDTH;
        let radius = this.RADIUS;
        ...
    }
}

Když vytvořím nový PointStyle let style=new PointStyle(styles).getStyle();, říká to že všechny proměnné třídy (this.FILL_COLOR,this.STROKE_COLOR,this.STROKE_WIDTH,this.RADIUS) jsou uvnitř createStyle() null. Proč? Neměla by třída být vytvořena se svými vlastnostmi? Měl bych je inicializovat v konstruktoru potomka a pak volat rodiče s super()?

Odpověď č. 1

Problém je v pořadí provádění. Inicializátory polí jsou jen syntaktickým cukrem pro pole přiřazená v konstruktoru, ale prvním příkazem provedeným v konstruktoru je základní konstruktor. Pokud se podíváme na generovaný kód, problém se stává jasnějším:

var PointStyle = /** @class */ (function (_super) {
    __extends(PointStyle, _super);
    function PointStyle() {
        // Super executed here !
        var _this = _super !== null && _super.apply(this, arguments) || this;
        //Field initialization here after createStyle is executed!
        _this.FILL_COLOR = 'rgba(255,255,255,0.4)';
        _this.STROKE_COLOR = '#3399CC';
        _this.STROKE_WIDTH = 1.25;
        _this.RADIUS = 5;
        return _this;
    }
    ...
    return PointStyle;
}(LayerStyle));
exports.PointStyle = P

Volání členů, které by měly být přepsány v konstruktorech, je obecně špatný nápad právě kvůli tomuto typu problémů, měli byste volat createStyle v odvozeném typu nebo přidat parametr, který potlačuje vykonávání createStyle, pokud je volán z odvozené třídy:

export abstract class LayerStyle {
    protected configuration: { [key: string]: string };
    protected style: ol.style.Style[];

    constructor(config: { [key: string]: string }, callInit: boolean = true) {
        this.configuration = config;
        if(!callInit) this.createStyle();
    }

    protected abstract createStyle(): void;

    getStyle() {
        return this.style;
    }
}

export class PointStyle extends LayerStyle {
    constructor(config: { [key: string]: string }, callInit: boolean = true) {
        super(config, false);
        if(callInit) this.createStyle();
    }
    //default values
    FILL_COLOR = 'rgba(255,255,255,0.4)';
    STROKE_COLOR = '#3399CC';
    STROKE_WIDTH = 1.25;
    RADIUS = 5;

    createStyle() {
        let fillColor = this.FILL_COLOR;
        let strokeColor = this.STROKE_COLOR;
        let strokeWidth = this.STROKE_WIDTH;
        let radius = this.RADIUS;
    }
}