2012-02-20 15 views
5

¿Por qué es que la siguiente es legal C#:Adición de acceso a la interfaz de propiedad permitido, pero no a la propiedad abstracta

public interface ISomeInterface 
{ 
    int SomeProperty 
    { 
     get; 
    } 
} 

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

pero esto no es:

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

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

Los últimos resultados en la siguiente error en tiempo de compilación:

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

¿Cuál es el razonamiento para no rechazar este último y permitir el anterior?

+0

Creo que la palabra kay aquí es "anular". No hay un método establecido para anular. –

+0

¿O es que la palabra clave de anulación se especifica en el nivel de propiedad en lugar del nivel de acceso? Después de todo, cada acceso es un método distinto cuando se trata de eso. –

+1

Derecha: la palabra clave abstracta funciona en el nivel de propiedad, no en el nivel de acceso. –

Respuesta

3

Debido a que una persona que llama mediante la interfaz sólo se preocupa de que un ejecutor de la interfaz al menos implementa la definición de la interfaz, como @davisoa estados, mientras que SomeAbstractClass en su ejemplo se define un contrato público que establece exactamente el tipo, la accesibilidad y (para propiedades) legibilidad/escritura de miembros.

Si usa el reflejo para obtener el PropertyInfo de SomeProperty (desde la clase base o secundaria), necesita resolver esa información desde algún lugar. Permitir que la clase infantil cambie la legibilidad/escritura sería una violación tanto del contrato como un cambio en el tipo de devolución o la lista de argumentos.

Imagínese por ejemplo:

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

Esto se debe a que la implementación de la interfaz promete que habrá una propiedad SomeProperty que podrá "obtener".

La implementación de la clase abstracta promete que sus clases secundarias proporcionarán una implementación de una propiedad SomeProperty con un método get público.

Al final, la clase base es la definición de algo que debe ser anulados , mientras que la interfaz es la definición de un contrato.

+0

Por lo que a mí respecta, 'SomeClassExtendingAbstractClass' * no * proporciona una propiedad' SomeProperty' con un método public get. Es irrelevante para cualquiera que trabaje contra la interfaz abstracta que también haya un colocador. Por lo tanto, mi pregunta. Imagine si cada uno de los get/set fueran métodos en su lugar. Imagine que no puede proporcionar un método 'SetValue' solo porque ha extendido una clase abstracta que tiene un método' GetValue'. –

+2

@KentBoogaart, esa es la cuestión: no son solo captadores y establecedores. Las propiedades son ciudadanos de primera clase en .NET y tienen metadatos contractuales sobre su legibilidad/escritura asociada con la propiedad. –

1

Está intentando anular un operador establecido que no existe. Defina una porción de conjunto de la propiedad en la clase abstracta o no intente definir una en la clase concreta. Como tiene el conjunto como protegido en la clase concreta, supongo que lo que quiere hacer es crear un operador de conjunto protegido en la definición abstracta.

0

Lo que es necesario es que tanto invalidar la propiedad existente y la sombra con una nueva lectura-escritura. Desafortunadamente, .net no proporciona ningún medio para anular y sombrear a un miembro dentro de una sola clase. Lo mejor que uno puede hacer es probablemente hacer que la clase base abstracta defina una propiedad concreta no virtual de solo lectura cuyo captador llama a una función abstracta. Una clase derivada puede sombrear la propiedad con una función de lectura y escritura no virtual que llama a la misma función en su getter, y una nueva función abstracta o virtual en su setter.

1

Esto es por diseño. Cito a partir de las especificaciones del lenguaje 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.

La razón detrás de esto decesion podría deberse a que las interfaces son más flexible tipo de contratos que las clases abstractas. Las interfaces solo se preocupan por el mínimo común denominador en lugar de la implementación completa. Creo que hay buenas razones para elegir un diseño sobre el otro.

Cuestiones relacionadas