2012-06-29 158 views
4

比方說,我有兩個基本的抽象類,具有完全不同的功能:筆記本電腦和智能手機。 (假設功能完全不同)。而在我目前的項目中,我已經有許多筆記本電腦和智能手機的實施,而且他們總是完全不同。多繼承和C#

但突然間,我收到一個要求添加一個pc-tablet實現的類,實際上它具有智能手機和筆記本電腦的功能。現在改變基礎類已經太晚了,實際上我非常肯定這款pc平板電腦只會出現一次。

問題是,我應該能夠在智能手機的conainer中容納我的pc-tablet,但它也應該是筆記本電腦,因爲繼承的功能(實際上除此之外,在項目pc-tablet的某些部分僅用於筆記本電腦,並不需要智能手機的功能,而且將PC平板電腦視爲該項目特定部分的智能手機也不好)。所以我有PcTabletAsLaptop:筆記本電腦類,這實際上是一臺筆記本電腦,而不是智能手機。

我的解決辦法是增加一個包裝:

class PcTablet : SmartPhone 
{ 
    private PcTabletAsLaptop _pcTablet; 

    // Here goes all the methods of PcTabletAsLaptop as proxies: 

    public void Call(int number) 
    { 
     _pcTablet.Call(number); 
    } 

    // ..... 
} 

有200+的方法,我想從PcTabletAsLaptop自動生成它們。

該解決方案看起來相當複雜。我的問題是好的,或者有一些簡單的方法可以做到這一點?

+0

你不能添加更多的基類「MobileDevice」,並讓它們都繼承它嗎? –

+0

200多種方法?也許是時候考慮一​​些重新設計。 –

+0

@DaveBish我不想改變原始層次,因爲該項目已經投入生產。實際上,這是客戶的要求(我們正在編寫框架,因此代碼設計也被視爲需求的一部分) – Archeg

回答

1

如果您需要多重繼承 - 在大多數情況下您做錯了某些事情或嘗試以錯誤的方式解決問題。層次結構如下所示?

internal class PcTabletAslaptop : LaptopBase 
{ 
    // here is you can expose/override laptop specific stuff 
} 

internal class PcTabletAsSmartphone : SmartphoneBase 
{ 
    // here is you can expose/override smartphone specific stuff 
} 

public interface IPcTablet 
{ 
    // just expose PcTablet specific API 
} 

public sealed class PcTablet : IPcTablet 
{ 
    private PcTabletAsSmartphone asSmartphone; 
    private PcTabletAsLaptop asLaptop; 
} 
+0

您的解決方案看起來像我的,因爲只有我從智能手機派生PcTablet。我想你的解決方案可能會更好。但是我仍然需要對這200多種方法進行代理,以便PcTablet調用其中一個字段。所以,我的問題是它應該如何? – Archeg

+0

因此,對於PcTablet類,筆記本電腦和智能手機類的公共API是不夠的,您需要訪問受保護的/專用的界面?如果可以,請在您需要訪問筆記本電腦/智能手機的私人/受保護的界面時帶上其中一個示例? – sll

+0

我的意思是PcTabletAsSmartphone有Call()方法,在這種情況下PcTablet也應該有Call()方法,它調用asSmartphone.Call()。我有200多種這樣的方法。當我隱藏PcTabletAsSmartphone時,我需要將此方法編寫爲隱藏內部實例的代理。當然,我可以將其作爲智能手機實例公開,但這會打破所有設計 – Archeg

3

您可以提取的接口形式既智能手機&筆記本電腦,然後創建第三個界面PcTablet將來自前兩個繼承。這樣,您就可以將PcTablet用作智能手機或筆記本電腦。

編輯:

爲了能夠重用邏輯每個智能手機&筆記本電腦裏面,你可以使用適配器模式使PcTablet應該像這樣的事情:

public class PcTablet :ISmartPhone, ILaptop 
{ 
    private SmartPhone _smartphone; 
    private Laptop _laptop; 
    public void ISmartPhone.Call() 
    { 
     _smartPhone.Call(); 
     // OR IMPLEMENT THE RIGHT BEHAVIOR 
     //INSTEAD OF CALLING _smartPhone.Call() 
    } 
} 

你當然必須在構造函數中創建一個智能手機和laptopn,但它應該做的伎倆!通過這種方式,您可以重複使用智能手機中的代碼,但也可以在不提供正確的情況下覆蓋其行爲。

+0

不錯的想法,但智能手機和筆記本電腦的基本邏輯又如何呢?我希望它能以最小的努力重複使用。 – Archeg

+0

@Archeg看我的編輯! –

+0

是的,這是很好,這是我第一次打算。唯一讓我感到害怕的是我必須爲_smartphone和_laptop的每種方法實現這些包裝(它們很多) – Archeg