2012-02-20 69 views
5

为什么,下面是合法的C#:添加访问接口属性允许的,但不是抽象属性

public interface ISomeInterface 
{ 
    int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassImplementingInterface : ISomeInterface 
{ 
    public int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

但这不是:

public abstract class SomeAbstractClass 
{ 
    public abstract int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassExtendingAbstractClass : SomeAbstractClass 
{ 
    public override int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

在以下后者结果编译时错误:

'InterfaceAbstractTest.SomeClassExtendingAbstractClass.SomeProperty.set': cannot override because 'InterfaceAbstractTest.SomeAbstractClass.SomeProperty' does not have an overridable set accessor InterfaceAbstractTest

在允许前者的同时不禁止后者的原因是什么?

+0

我认为他们在这里的话是“覆盖”。没有设置的方法来覆盖。 – 2012-02-20 17:00:30

+0

或者,是否在属性级别而不是访问者级别指定了override关键字?毕竟,每个访问者在涉及它时都是一个独特的方法。 – 2012-02-20 17:02:40

+1

右键 - 抽象关键字在属性级别,而不是访问者级别。 – 2012-02-20 17:04:51

回答

3

因为使用接口调用者只关心该接口至少的实施者实现了接口的定义,@davisoa状态,而在你的例子SomeAbstractClass定义其中规定公共合同完全型,交通方便,和(用于属性)成员的可读性/可写性。

如果使用反射来获取SomeProperty的PropertyInfo(来自基类或子类),它需要从某处解析该信息。允许子类更改可读性/可写性与返回类型或参数列表中的更改一样,会违反合同规定。

试想例如:

SomeAbstractClass sc = new SomeClassExtendingAbstractClass(); 
PropertyInfo pi = sc.GetType().GetProperty("SomeProperty"); 
Console.Out.WriteLine(pi.CanWrite); // What should be printed here? 
2

这是因为该接口实现正在作出承诺,将会有一个属性SomeProperty,你可以“搞定”。

抽象类实现承诺它的子类将使用公共get方法提供属性SomeProperty的实现。

在结束时,将基类定义的东西必须重写,而所述接口被限定合同一个

+0

就我而言,'SomeClassExtendingAbstractClass' * *提供了一个带有公共get方法的'SomeProperty'属性。对抽象接口工作的人来说,这也是无足轻重的。因此,我的问题。想象一下,如果每个get/set都是方法的话。想象一下,仅仅因为你扩展了一个具有'GetValue'方法的抽象类,就无法提供'SetValue'方法。 – 2012-02-20 17:05:10

+2

@KentBoogaart就是这样的事情 - 他们不只是获得者和制定者。属性是.NET中的一等公民,并且具有关于与该属性相关的可读性/可写性的契约元数据。 – 2012-02-20 17:07:27

1

您试图覆盖不存在的集合运算符。要么在抽象类中定义属性的集合部分,要么不要在具体类中定义一个属性。既然你把这个集合作为具体类中的保护对象,我的猜测是你想要做的是在抽象定义中创建一个受保护的集合运算符。

0

所需要的是既覆盖现有的财产,并用新的阴影成可读写之一。不幸的是.net没有提供任何覆盖和遮蔽单个类中的成员的手段。最好的做法可能是让抽象基类定义一个具体的非虚拟只读属性,它的getter调用一个抽象函数。然后,派生类可以使用非虚拟读写函数来映射该属性,该函数在其getter中调用相同的函数,并在其setter中创建一个新的抽象函数或虚函数。

1

这是设计。我从C#语言规格报价:

An overriding property declaration must specify the exact same accessibility modifiers, types and name as the inherited property, if the inherited property has only a single accessor (i.e.,... ready only or write-only), the overriding property must include only that accessor.

是decesion背后的原因可能是因为接口更加灵活的合同不是抽象类的类型。接口只关心最不共同的部分,而不是整个实现。我认为有充分的理由选择另一种设计。