简体   繁体   中英

How to extend factory method in typescript

Context:

I have some class which at some point produces instances of itself, and it works fine. But now I would like to extend that class and realize that I would get an instance of a parent class.

Example:

class Line {
    constructor(protected length: number) {}
    
    divide(into: number): Line[] {
        const size: number = Math.ceil(this.length / into);

        return (new Array(into)).map(() => new Line(size));
    }
}

class BoldLine extends Line {
    constructor(protected length: number, private width: number) {
        super(length);
    }

    getWidth() {
        return this.width;
    }
}

const line: BoldLine = new BoldLine(10, 2);

line.divide(2); // <== I'll get Line[] but would like to have BoldLine[];

Question:

How can I always get the instance of this.constructor class, even after inheritance? And how can I do this in a seamless way, w/o passing constructor name as a parameter for divide method?

Thanks.

Not sure if there is a better approach, but this is how I would do it.

class Line {
    constructor(protected length: number) {}
    
    divide(into: number): this[] {
        const size: number = Math.ceil(this.length / into);

        return (new Array(into)).map(() => new (this.constructor as new (length: number) => this)(size));
    }
}

class BoldLine extends Line {
    constructor(protected length: number, private width) {
        super(length);
    }

    getWidth() {
        return this.width;
    }
}

const line: BoldLine = new BoldLine(10, 2);

line.divide(2);

If you need the width property (which is untyped so it could be anything, including undefined) to be propagated to child classes, then you need an additional factory method for instances of the current class.

class Line {
    constructor(protected length: number) { }

    protected create(length: number): this
    {
        return new Line(length) as this;
    }
    
    divide(into: number): this[] {
        const size: number = Math.ceil(this.length / into);

        return (new Array(into)).map(() => this.create(size));
    }
}

class BoldLine extends Line {
    constructor(protected length: number, private width) {
        super(length);
    }

    protected create(length: number): this
    {
        return new BoldLine(length, this.width) as this;
    }
    
    getWidth() {
        return this.width;
    }
}

const line: BoldLine = new BoldLine(10, 2);

line.divide(2);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM