多继承和C#

问题描述:

比方说,我有两个基本的抽象类,具有完全不同的功能:笔记本电脑和智能手机。 (假设功能完全不同)。而在我目前的项目中,我已经有许多笔记本电脑和智能手机的实施,而且他们总是完全不同。多继承和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

我认为你可以用组合而不是聚合来思考。

aggregation-vs-composition

什么SmartPhone包含Tablet

如果您需要多重继承 - 在大多数情况下您做错了某些事情或尝试以错误的方式解决问题。层次结构如下所示?

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

您可以提取的接口形式既智能手机&笔记本电脑,然后创建第三个界面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