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

时间:2009-06-07 02:43:05

标签: c#

给出以下内容:

class A : B {}

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

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

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

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

7 个答案:

答案 0 :(得分:12)

试一试

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;

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

不,你不能。至少没有C#4.0的协方差/反演度特征。

答案 3 :(得分:1)

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

另外,我将不同意保罗:我认为差异不会对你的情况有所帮助。 看看Skeet对方差here所说的内容。

答案 4 :(得分:1)

不,假设如下:

class D : B {}

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

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

此规则遵循Liskov Substitution Principle

P.S。我要感谢Troels Knak-Nielsen对这一微妙之处的开放态度。

答案 5 :(得分:0)

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

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

答案 6 :(得分: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; }
}

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