2009-06-07 75 views
3

给出如下:我可以在C#中使用子类实现接口吗?

class A : B {} 

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

我能做到这一点不知?

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

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

+0

如果这是可能的话,它肯定会混淆未来的代码维护者。你的意图是什么?如果你遇到这个问题,你应该重构。 – 2009-06-07 03:48:46

回答

11

试试这个

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

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

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

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

1

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

另外,我不同意Paul的看法:我认为差异对你的情况没有帮助。 看看Skeet关于差异here的说法。

2

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

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

我不太明白你的例子。它应该不是:A是-A B,​​但B不是A?另外,B应该是Vehicle和A Boat,我会是Mobile。然后,另一个D类飞机(这将是Vehicle)不能分配给TheObject,因为它需要一个Boat,而不是Mobile在Mobile界面中声明的。我错过了什么吗? – 2009-06-07 03:49:26

+0

@Ionut:是的,你说得对,我需要解决。 – 2009-06-07 05:09:52

1

号,以下假设:

class D : B {} 

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

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

此规则遵循Liskov Substitution Principle

P.S.我想感谢Troels Knak-Nielsen,让我对这个微妙的事情大开眼界。

0

你在想什么是协变/逆变,但即使在C#4.0中也不行。如果您只有对接口的引用,它仍然需要可用。

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

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; } 
} 

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

相关问题