繁体   English   中英

我可以在C#中使用子类实现接口吗?

[英]Can I implement an interface using a subclass in C#?

给出以下内容:

class A : B {}

interface I
{
 B TheObject {get;set;}
}

我能以某种方式这样做吗?

class C : I
{
 public A TheObject {get;set;} 
}

请注意,接口具有基类,实现具有子类。

试一试

class C : I
{
 public A TheObject {get;set;} 
 B I.TheObject 
 {
   get { return A; }
   set { A = value as A; }
 }
}

您可能需要根据需要修改B setter。 以这种方式实现接口具有以下结果。 处理类型为C的变量时,您将无法访问B TheObject。 如果需要,您需要声明一个I变量并将其分配给您的C var。 以这种方式实现我称为显式实现。

例如

C c = new C();
A a = c.TheObject; // TheObject is an A
I i = c;
B b = i.TheObject;

您无法执行此操作,因为接口实现的返回类型必须匹配。 但是,我为什么不能这样做的理由是错误的(正如评论中所指出的那样)。 您必须匹配签名,但您可以从C返回一个新的A ...

public class C : I
{
  public B TheObject { get { return new A(); } set {} }
}

不,你不能。 至少没有C#4.0的协方差/逆变量功能。

不。 编译器会抱怨类型不匹配。

此外,我将不同意保罗:我认为差异不会对你的情况有所帮助。 看看Skeet 在这里对方差的看法。

不,假设如下:

class D : B {}

C c = new C();
c.TheObject = new D(); // error. D is not A, A is not D

使用上面的类我仍然可以使用D实现接口I对象,但我们假设我想将C实例的TheObject属性设置为D的实例。 我不能,因为DA是兄弟姐妹。 它们都继承自同一个类,因为它们在界面中会很好,但是声明你期望A困扰编译器。 A的实例不是D的实例,但A和D的实例都是B的实例。

这条规则遵循Liskov替代原则

PS我想感谢Troels Knak-Nielsen对这一微妙之处的开放态度。

您所考虑的是协方差/逆变,但即使使用C#4.0,这也行不通。 如果您只有对接口的引用,它仍然需要可用。

getter可以工作,因为A也是B,但是setter不能工作,因为实现需要A,而接口允许你将TheObject设置为B.通常,返回值可以是子类型,参数可以是具有协方差/逆变的基类型。 但仅限于C#4.0。

这编译:

class B { }

class A : B { }

interface I<T> where T : B
{
    T TheObject { get; set; }
}

class C : I<A>
{
    public A TheObject { get; set; }
}

但我认为这不是你想要的?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM