2011-07-28 85 views
7

我一直在試圖產生應該返回一個通用接口根據輸入參數的函數的不同對象(比如Item)(我把它叫做一個上下文)現在getItem(A context)C#中的靜態方法的多態性和重載。

一廠,假設我定義了一個新的上下文類型:B,它繼承自A

我想返回一個不同的項目,這取決於傳遞給工廠的對象是否爲BA

我試着做如下(重載方法):

class Factory 
{ 
    static Item getItem(A context) {...} 
    static Item getItem(B context) {...} 
} 

這工作得很好,如果我做這樣的事情:

B bContext=new B(); 
Item it=Factory.getItem(bContext); 

但是,如果我投和對象類型A

A bContext=(A) new B(); 
Item it=Factory.getItem(bContext); 

第一種工廠方法被調用。

我認爲即使在演員演員之後,多態性也能確保第二種方法的執行,並且我想知道我是否遺漏了某些東西?

我知道我可以繼續使用單一方法,並使用is運算符來檢查變量的類型,但我認爲我上面介紹的解決方案更優雅一些。

回答

10

超載在編譯時決定(除了在C#4使用動態類型)的基礎上的參數的編譯時類型 - 在你的最後片段,參數的編譯時類型爲A ,所以它叫Factory.getItem(A)

只有虛擬方法調用是多態的(使用覆蓋),其中目標對象的實際執行時間類型決定調用哪個實現。如果AB有一個虛擬方法(在B中被覆蓋)可以通過Factory.getItem調用來處理差異,那很好......否則,您會被動態輸入或is之類的東西卡住。

1

你無法實現你假裝現在設置事物的方式。

一個選擇是在工廠方法中有一些邏輯可以區分參數的類型。笨重,不漂亮,但它的工作原理:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     if (context is ContextB) {...} 
     else {...} 
    } 
} 

另一種選擇是使上下文對象負責創建對象。例如:

public class ContextA 
{ 
    .... 
    internal virtual Item CreateItem() { //specific creation logic for ContextA } 
} 

public class ContextB: ContextA 
{ 
    .... 
    internal override Item CreateItem() { //specific creation logic for ContextB } 
} 

現在,你可以這樣做:

class Factory 
{ 
    static Item getItem(ContextA context) 
    { 
     return context.CreateItem(); 
    } 
} 

沒有,如果你做到以下幾點:

ContextA context = new ContextB(); 
Item item = Factory.getItem(context) 

ContextB.CreateItem()將被調用。