接口,继承和多态的麻烦

时间:2011-09-15 17:14:49

标签: c# inheritance

我已经在程序中找到了我的多态性被打破的地方。我意识到这是在我的代码中,我理解为什么;我只是不确定如何最好地解决它。

我有三个模型类,它们具有相同的接口,但实现却非常不同。我创建了一个接口,然后创建了三个独立的类,这些类也派生自ModelBase类:

public interface IMyModel
{ ... }

public class MyModelA : ModelBase, IMyModels
{ ... }

public class MyModelB : ModelBase, IMyModels
{ ... }

public class MyModelC : ModelBase, IMyModels
{ ... }

到目前为止很精致和花花公子。

我有一个ViewModel基类,它将模型作为构造函数:

public abstract class MyViewModelBase
{
    public MyViewModelBase(ModelBase Model)
    this.model = Model;
}

现在我被抓住了;我想要一个具体的ViewModel类,它可以接受上面三个Model类中的任何一个:

public class MyViewModel : MyViewModelBase
{
    MyViewModel(IMyModel Model) : base (Model)   // <- Invalid Polymorphism!
    {
        // More here
    }
}

这不起作用,因为IMyModel的实现可能不基于ModelBase。参数无法安全地传递给基础构造函数。

我可以看到一个解决方案是为具有异常抛出内容的这些模型创建一个从ModelBase派生的抽象基类,并将其用作我的ViewModel中的类型。我从一个基类开始,但发现几乎每个部分都有一些区别!然而,这似乎很多工作。此外,它不会确保派生类实现所有内容(如接口一样)。最后,它似乎贬低了界面概念(实际上,我不再需要它了)。

我没有看到任何标记接口的方法,因为派生类必须具有特定的基类。如果我能做到这一点会很好,但是不允许这样做:

public interface IMyModel : MyModelBase
{ ... }

有更好的方法吗?

澄清:

我可能在这里过分简化了名字。我有其他模型和ViewModel使用基类,但没有实现接口。

public class MyOtherModel : ModelBase  // But not IMyModel!
{ ... }

public class MyOtherViewModel : MyViewModelBase
{
    MyOtherViewModel(MyOtherModel Model) : base(Model)  // This works
    { ... }
}

5 个答案:

答案 0 :(得分:2)

您可以使用通用约束:

public class MyViewModel<T> : MyViewModelBase where T : IMyModel , ModelBase
{
    MyViewModel(T model) : base (model)   // T inherits ModelBase and implements IMyModel , so it is legal
    {
        // More here
    }
}

答案 1 :(得分:2)

您可以使您的基类实现接口,然后从基类继承您的实现类,将基类和方法标记为抽象(VB术语中的MustInherit / MustOverride)。这将为您提供多态性并保证接口。

答案 2 :(得分:1)

当您发现自己构建抽象基类时,通常(并非总是)意味着您正在尝试共享接口和一些常见逻辑。也许你可以将这两件事分开?

将公共接口移动到IMyModel中,并将公共功能提取到单独的类中。然后在每个模型中包含该帮助程序类的实例。基本上使用组合来共享功能而不是继承。

答案 3 :(得分:0)

让ModelBase实现IMyModel。如果ModelBase没有实现接口的所有方法,请将它们实现为抽象方法。

答案 4 :(得分:0)

据我所知

  • 模型是愚蠢的数据容器
  • 接口描述行为和功能,而不是数据。

那么为什么要在模型上放置接口呢?

@Yochai:好点,使用Generics - 保存代码,但你必须首先声明基类(每个类只有一个,C#中没有混合继承),然后是任意数量的接口,因此你的代码应该是:

public class MyViewModel<T> : MyViewModelBase where T : ModelBase, IMyModel