2017-03-09 95 views
1

我有兩個子類的父類:打字稿:如何設置方法的返回值=>子類

abstract class Point { 
    public readonly x: number; 
    public readonly y: number; 

    constructor(x: number, y: number) { 
     this.x = x; 
     this.y = y; 
    } 

    diff(point: Point): Point { 
     return this.update(this.x - point.x, this.y - point.y); 
    } 
    // many methods like diff(); and then... 

    protected abstract update(x: number, y: number): Point; 
} 



class ImmutablePoint extends Point { 
    protected update(x: number, y: number): Point { 
     return new ImmutablePoint(x, y); 
    } 
} 



class MutablePoint extends Point { 
    public x: number; 
    public y: number; 

    protected update(x: number, y: number): Point { 
     this.x = x; 
     this.y = y; 
     return this; 
    } 
} 


const pointA: ImmutablePoint = new ImmutablePoint(10, 10) 
const pointB: ImmutablePoint = new ImmutablePoint(6, 2); 

diff()方法返回一個點,而不是一個ImmutablePoint

// Error: type 'Point' is not assignable to parameter of type 'ImmutablePoint'. 
const result: ImmutablePoint = pointA.diff(pointB); 

我尋找一種方法來重新定義子類上的方法簽名而不寫一個新的實現,這有可能嗎?

我也試圖讓diff()返回值this但它不工作,因爲ImmutablePoint不返回this而是一個新的ImmutablePoint

Playground Link

+1

爲什麼筆記只是做類型'Point'的'result'?代碼改爲「界面」。 – Carcigenicate

+0

是的,事實上,你可以在任何地方使用超類作爲類型而不是子類,但是爲什麼我們使用ImmutablePoints的原因主要是作爲(不可變的)參數,並且每次都必須傳遞一個Point。非常煩人。其實只是看到我粘貼的錯誤說「類型參數」:P –

回答

2

您可以Point通用:

abstract class Point<T extends Point<any>> { 
    public readonly x: number; 
    public readonly y: number; 

    constructor(x: number, y: number) { 
     ... 
    } 

    diff(point: Point<any>): T { 
     return this.update(this.x - point.x, this.y - point.y); 
    } 

    protected abstract update(x: number, y: number): T; 
} 

class ImmutablePoint extends Point<ImmutablePoint> { 
    protected update(x: number, y: number): ImmutablePoint { 
     return new ImmutablePoint(x, y); 
    } 
} 

class MutablePoint extends Point<MutablePoint> { 
    public x: number; 
    public y: number; 

    protected update(x: number, y: number): MutablePoint { 
     ... 
     return this; 
    } 
} 


const pointA: ImmutablePoint = new ImmutablePoint(10, 10) 
const pointB: ImmutablePoint = new ImmutablePoint(6, 2); 
const result: ImmutablePoint = pointA.diff(pointB); // fine 

code in playground

隨着所提供的新功能Default generic type variables你應該能夠做這樣的事情:

abstract class Point<T extends Point = Point> { 
    ... 
} 

(沒有測試它尚未)

+0

這是天才,非常感謝你:) –