2014-12-02 113 views
1

我有兩個類都實現了IFruit接口。簡化的問題是我想在某些情況下用芒果代替蘋果。但是下面的例子會導致編譯器錯誤。打字稿對象轉換錯誤

無法將'Mango'轉換爲'Apple':類型'Mango'和'Apple'將屬性'_element'定義爲私有。

爲什麼這是一個問題?界面中不顯示_element。它不應該被迫公開。

​​

回答

2

有三種解決方案可以使用,選擇是基於上下文的。

接口

因爲私有成員有效地使它不可能對任何其他類型的在結構上一場比賽,你永遠不能讓一個Mango看起來像一個Apple。他們都完全滿足IFruit接口,所以如果你是IFruit鍵入他們,他們是完全substituatble - 比如下面兩個new Apple(e)new Mango(e)IFruit類型註釋 - 雖然這與它的工作只是Apple,例如:

interface IFruit { 
    getElement(): HTMLElement; 
} 

class Apple implements IFruit { 

    private _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 
} 

class Mango implements IFruit { 

    private _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 

} 

var e: HTMLElement; 
var a: IFruit = new Apple(e); 
var m: IFruit = new Mango(e); 
a = m; 

繼承

你也可以使用繼承來解決這個問題。 AppleMango可以訪問的基礎上保護_elementFruit類:

class Fruit { 
    protected _element : HTMLElement; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 
} 

class Apple extends Fruit { 
    constructor(element: HTMLElement) { 
     super(element); 
    } 
} 

class Mango extends Fruit { 
    constructor(element: HTMLElement) { 
     super(element); 
    } 
} 

var e: HTMLElement; 
var a = new Apple(e); 
var m = new Mango(e); 
a = m; 

公共

如果你想讓他們不使用界面還是繼承兼容,你需要做的財產公開:

interface IFruit { 
    getElement(): HTMLElement; 
} 

class Apple implements IFruit { 

    public _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 
} 

class Mango implements IFruit { 

    public _element; 

    constructor(element: HTMLElement) { 
     this._element = element; 
    } 

    getElement(): HTMLElement { 
     return this._element; 
    } 

} 

var e: HTMLElement; 
var a = new Apple(e); 
var m = new Mango(e); 
a = m; 
+0

我去了第一個選項。但我仍然認爲這很奇怪。如果兩者都有相同的私人成員,那麼它應該可以工作。如果「元素」是公共的而非私人的,它也可以工作。 – 2014-12-02 13:43:25

+2

這是結構分類系統的本質 - 如果要應用領域驅動設計,能夠創建非匹配類型非常重要。例如'class CustomerId {constructor(private id:number){} getId(){return this.id; }}'不能被誤認爲'class ProductId {constructor(private id:number){} getId(){return this.id; }}'Playground上的示例:http://bit.ly/1FKUkxE – Fenton 2014-12-02 13:48:26

+0

上述評論中的代碼示例很難閱讀,但在此處更詳細地寫入:https://www.stevefenton.co.uk /內容/博客/日期/ 201412 /博客/爲什麼私營成員對結果的In-風雨同路,打字稿,結構/ – Fenton 2014-12-02 14:05:17