2011-07-21 56 views
2

我試圖很難找到這個問題的答案,所以如果它已被問到,也許我寫錯了。我有一個抽象基類和派生類。在實現一個抽象基類作爲參數的接口方法時訪問派生類屬性

abstract class Foo 
{ 
    protected int property1 
    protected int property2 
// etc.. 
} 

我dervied類包含未在基類中發現了一些額外的屬性:

class Fum : Foo 
{ 
    public int UniqueProperty { get; set; } 
} 

現在我有,是以抽象基類中的方法的接口:

interface IDoSomethingWithFoos 
{ 
    void DoSomethingWithFoo(Foo fooey); 
} 

實現接口的類

class FumLover : IDoSomethingWithFoos 
{ 
    void DoSomethingWithFoo(Foo fooey) 
    { 
     // now in here i know i am going to be passed objects of Fum 
     // and i want to access its unique properties 

     fooey.UniqueProperty = 1; // this doesn't work 

     ((Fum)fooey).UniqueProperty = 1; // this seems to work 

     // as does.. 

     Fum refToFum = fooey as Fum; 
     refToFum.UniqueProperty = 1; 

    } 
} 

所以我的問題是:我正在以正確的方式來解決這個問題嗎?雖然這樣編譯,但我沒有足夠的代碼來確保它實際上能夠正常工作。而我的另一個問題是:這是不好的設計?有沒有更好的辦法?

*

更詳細地說明了一點,因爲自然的反應是,如果你將要路過FUM,然後讓接口方法採取FUM,而不是一個Foo的。

但是,讓我們說在我的FumLover類中,方法DoSomethingWithFoo使用屬於抽象低音類中的屬性處理95%。假設我有另一個名爲Fie的派生類,它有幾個獨特的屬性。現在假設我有一個FieLover類,並且我想實現DoSomethingWithFoo,因爲我在這裏要做的95%可以適用於所有Foo,但是再次,Fie有一點獨特之處。

什麼是替代方案?爲每個人提供一個接口:IDoSomethingWithFums,IDoSomethingWithFies等?看起來像是我失去了5%差異的所有抽象。

回答

3
// now in here i know i am going to be passed objects of Fum 
    // and i want to access its unique properties 

這是設計更改可能有所幫助的線索。您當前的界面顯示「我在Foo s上工作」。如果該實現僅適用於Fum,那麼您在說什麼和正在做什麼時會出現不匹配。如果您真的只希望得到Fum s,則在界面中聲明該參數爲Fum

如果你不想這樣做,那麼使用as語法是最好的,因爲那麼你不拋出一個異常,當有人認爲他們可以在Foo通(因爲哎,接口他們可以)

as代碼應該是這樣的:

Fum fumObj = fooey as Fum; 
if (fumObj != null) 
    fumObj.UniqueProperty = 1; 

更新

你對每個派生類的接口的建議實際上是可取的(因爲他們說他們實際上做了什麼),但讓我們退一步:你究竟在這裏試圖完成什麼?如果你想IDoSomethingWithFoos利用Foo的地方作爲基類(雖然是抽象的),那麼你需要確保調用DoSomethingWithFoo對所有Foo有意義。如果沒有,那麼你已經輸了,因爲即使你要求是一個FooLover,你真的只愛Fum S(或Fie秒)

一個解決辦法是做Foo本身聲明abstract DoSomething()方法。現在,你可以有一個List<Foo>,並有這樣的代碼:

foreach (Foo foo in fooList) 
    foo.DoSomething(); 

現在,你實際上正在抽象的優勢。你不在意這些是什麼樣的Foo這些是:他們都做了一些事情,可能基於只有派生類別獨有的屬性(不需要強制轉換)。

+0

嗯,但糾正我,如果我錯了,但由於接口需要一個抽象類,它總是要在派生類的實例(無論是Fum或其他類)。從抽象類派生一個類如果不是爲它添加一些獨特的屬性又有什麼意義?這幾乎就像界面所說:「我必須與這個抽象基類的派生類一起工作,但不能與它們的任何獨特方面一起工作」。 – suite16

+0

這是真的,但通常當你有一個方法接受一個派生類型較少的版本時,你期望它能夠完成它的工作,而不需要訪問更多的派生屬性。這並非總是如此(通常當你暴露一個API時),但往往是這樣。我的意思是,如果你的實現*需要來自派生類型的*信息,那麼聲明這樣的參數可能會有幫助。正如我上面所說的,如果你不關心(這很好),至少使用'as'選項,所以你不會拋出不必要的異常。 – dlev

+0

@ suite16這是_is_接口說的(種類)。每個派生類可以有不同的方式,但是一旦你必須知道某個實現獨有的屬性或方法,你就失去了首先使用基類的好處。 –

-1

我認爲你所做的很好,因爲Fum擴展Foo你應該能夠以你自己的方式投射它。

另一種方法是實現一個IFoo接口並將其傳遞給方法。

+0

那麼當傳遞一個不是'Fum'的'Foo'時會發生什麼?此代碼將在投射失敗時引發異常。另外,如果你總是想把它用作'Fum',爲什麼要把它聲明爲'Foo'? –

+0

如果你不想總是通過'Fum'會怎麼樣?如果你有其他類從'Foo'派生的類呢?您的解決方案不涉及任何前瞻性思維。我會想,鑑於他知道「類繼承」的事實,他會知道在嘗試訪問它們之前檢查「null」對象。另外,如果你傳遞一個不會擴展'Foo'的類,它將不會編譯。請刪除-1。 – simonlchilds

+0

PS我在等火車的時候寫了我的答案。因此沒有代碼片段。 – simonlchilds

相關問題