【问题标题】:Allowing implementing interface only for specific classes只允许为特定类实现接口
【发布时间】:2011-04-23 21:47:02
【问题描述】:

是否可以只允许某些特定的类来实现一个 iterface? 假设我创建了接口IMyInterface,并且我只希望派生自UserControl 的类能够实现我的接口。这可能吗?

【问题讨论】:

  • 我仍然在考虑接口与抽象类,但我认为您的问题揭示了接口的实际意义。如果您的接口仅与某些类兼容,则它可能太大(两个较短的接口可能更可重用)或太小(实现类需要具有某些方法/属性才能工作......这就是接口要确保的)

标签: c# inheritance interface


【解决方案1】:

你不能,但是你可以通过向你的界面添加一个 Control 属性来实现类似的东西,并且按照惯例让所有实现都返回this。不能解决你的问题,但会让实现者思考一下接口是否真的属于那里。还允许界面的用户以类型安全的方式检索控件而无需强制转换。

interface IMyInterface
{
    void Foo();
    UserControl Control { get; }
}


class MyControl : UserControl, IMyInterface
{
    public void Foo()
    {
        // TODO: Write code here
    }

    UserControl IMyInterface.Control
    {
        get { return this; }
    }
}

更新

还有另一种解决方案 - 制作通用方法。接口本身不会受到限制,但操作的方法会受到限制。例如下面的方法要求其参数既继承UserControl又实现IMyInterface

void Bar<T>(T item)
  where T : UserControl, IMyInterface
{
    item.Width = 120;    // user control property
    item.Foo();          // IMyInterface method
}

【讨论】:

    【解决方案2】:

    我意识到这是一篇旧帖子,但我必须解决这个问题。

    你可以这样做:

    class BaseClass { }
    
    interface OnlyBaseClass<TSelf> where TSelf : BaseClass, OnlyBaseClass<TSelf>
    {
    
    }
    
    class ChildClass : BaseClass, OnlyBaseClass<ChildClass> { }
    
    class ImpostorClass : OnlyBaseClass<ImposterClass> { }
    
    interface ImposterInterface : OnlyBaseClass<ImposterInterface > { }
    

    尝试编译上面的。您会注意到它无法编译(由于两个冒名顶替者,一个是类,一个是接口)。

    TSelf上的约束可以理解为:

    TSelf 必须:从 BaseClass 继承实现 OnlyBaseClassTSelf>

    ...只有从 BaseClass 继承并实现 OnlyBaseClass 的类型才能做到。

    你可以很聪明,做以下事情:

    class AdvancedImpostorClass : OnlyBaseClass<ChildClass> {}
    

    ... 这将编译。您可以通过在任何接受它们作为参数的方法中使用相同的约束来防止这些类型的冒名顶替者进入您的代码,如下所示:

    public SomeMethod<TBaseAndInterface>(TBaseAndInterface value)
        where TBaseAndInterface: BaseClass, OnlyBaseClass<TBaseAndInterface>
    { }
    

    这一切都得益于F-Bound Polymorphism 的力量。

    【讨论】:

      【解决方案3】:

      听起来你想要这样的东西:

      abstract class IMyInterface : UserControl { }
      

      当然IMyInterface 不再是一个合适的名称,但任何派生自IMyInterface 的类也将派生自UserControl,这将满足您的要求。

      【讨论】:

      • 这听起来像是对上述问题的最合适的答案,但有一个警告:只有当您拥有所有希望使用的 UserControl 派生类的源代码时,它才有效。抽象类必须“插入”在 UserControl 和您正在使用的所有 UserControl 派生类之间,只有在您可以更改所有派生类的源代码时才能做到这一点)
      • 你需要类的多重继承才能使用多个接口来做到这一点(所以在 c# 中是不可能的):(。如果你只有一个接口来设置,那么解决方案很棒
      【解决方案4】:

      这是不可能的。如果你能看到接口,你就可以实现它。

      【讨论】:

      • 接口也是如此。但是,如果您拥有所有希望应用“接口”的类的源代码,则可以将抽象类插入派生链中以达到所需的效果。跨度>
      • @Jason Williams:即使一个人拥有一个接口的所有预期实现的源代码,但这并不意味着一个人能够为所有将实现的类定义一个共同的祖先界面。
      【解决方案5】:

      不,没有办法将接口的实现限制为特定类型。为什么你需要?为什么抽象的消费者关心实现该契约的具体类型?你的用例是什么?

      【讨论】:

      • +1,阿门Why does the consumer of an abstraction care about the concrete types that implement that contract?
      • 通常对于 UserControl 界面效果更好,并允许 Visual Studio 中的设计人员正确地以图形方式编辑用户控件。因此,有时我们会使用继承 UserControl 的抽象类,否则我们会重新使用用户控件的接口
      • 界面可能会关心。它可能有一些扩展方法,假设它正在实现的类是特定类型的。
      【解决方案6】:

      您描述的情况似乎适合“父类中的抽象方法”(此处为 userControl),除非该接口已经存在用于其他目的。

      如果没有默认主体,派生类将不得不提供一种行为。

      【讨论】:

        猜你喜欢
        • 2014-05-09
        • 2015-05-13
        • 2011-05-16
        • 2012-11-19
        • 2012-10-16
        • 1970-01-01
        • 2012-12-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多