2011-05-19 8 views
16

¿Por qué se permite cambiar la visibilidad y la existencia de getters o setters en una propiedad cuando se implementa una interfaz?Agregando setters a las propiedades en overrides

interface IFoo 
{ 
    string Bar { get; } 
} 

class RealFoo : IFoo 
{ 
    public RealFoo(string bar) 
    { 
     this.Bar = bar; 
    } 

    public string Bar { get; private set; } 
} 

class StubFoo : IFoo 
{ 
    public string Bar { get; set; } 
} 

... y no es legal hacer lo mismo al implementar una clase abstracta?

abstract class AbstractFoo : IFoo 
{ 
    public abstract string Bar { get; } 
} 

class RealFoo : AbstractFoo 
{ 
    public RealFoo(string bar) 
    { 
     this.Bar = bar; 
    } 

    // Cannot override because 'Bar' does not have an overridable set accessor 
    public override string Bar { get; private set; } 
} 
+2

En su ejemplo, está * agregando * código a la implementación de la interfaz, ya que no existía un setter, pero está * cambiando * la visibilidad en la implementación de la clase abstracta. Entonces no es lo mismo. – jv42

+1

@ jv42 No se cambia la visibilidad en la implementación porque el colocador es * privado *. La restricción es arbitraria y tonta ... C# podría especificarse también para permitir que la anulación solo se aplique para obtener o establecer cuando no sean privados. O podría permitir 'public string Bar {anular get; conjunto privado; } ' –

+0

@JimBalter Estoy de acuerdo en que podría haber mecanismos para cambiar la visibilidad de los usuarios. Es posible que desee comprobar lo que viene en C# 6, he visto algunas cosas nuevas interesantes para las propiedades. – jv42

Respuesta

12

La interfaz declara qué propiedades públicas debe tener la clase (es solo un contrato). Lo que significa que necesita tener esas propiedades, pero puede agregarlas.

La clase abstracta declara la estructura real de esas propiedades. Entonces, si no tiene el colocador en la base abstracta, no puede agregarlo en la implementación.
Cuando escribe el modificador de anulación, busca en la clase base algo que sobrescribir.

0

Una clase abstracta es una clase que no puede crearse una instancia, pero debe ser heredada de. Una clase abstracta puede implementarse completamente, pero generalmente se implementa parcialmente o no se implementa en absoluto, encapsulando así la funcionalidad común para las clases heredadas.

Una interfaz, por el contrario, es un conjunto de miembros totalmente abstracto que puede considerarse como la definición de un contrato de conducta. La implementación de una interfaz se deja completamente al desarrollador.

tomado de la MSDN http://msdn.microsoft.com/en-us/library/scsyfw1d(v=VS.71).aspx

+1

Bien, esto significa que agregar una clase base abstracta en la jerarquía de clases te obligará a agregar una implementación de instalador vacía/de excepción en algunas clases derivadas. No es el comportamiento más elegante. – ndeuma

+2

Esta "respuesta" no toca la pregunta realmente hecha. –

0

De acuerdo con la especificación de C#

Un elemento de acceso que se utiliza para implementar una interfaz puede no tener un de acceso-modificador. Si sólo hay un de acceso se utiliza para implementar una interfaz , el otro descriptor de acceso puede ser declara con un descriptor de acceso modificador:

public interface I 
{ 
    string Prop { get; } 
} 
public class C: I 
{ 
    public Prop { 
    get { return "April"; }  // Must not have a modifier here 
     internal set {...} // Ok, because I.Prop has no set accessor 
    } 
} 

Eso significa que está bien tener un acceso modificado en una clase que implementa la interfaz. Sin embargo, la clase abstracta declara una implementación y no puede cambiar eso con una clase derivada.

+1

las propiedades 'abstractas' no tienen implementaciones. ¿A qué te refieres con "la clase abstracta declara una implementación"? ¿Que una clase abstracta limita arbitrariamente la implementación mientras que una interfaz no limita arbitrariamente la implementación? – binki

+0

Sí, las clases abstractas pueden tener implementación. Una clase abstracta puede carecer de implementación o podría implementarse de manera incompleta. Se supone que una clase abstracta solo debe usarse para derivar otras clases. –

+1

"las clases abstractas pueden tener implementación" - @binki dijo que las propiedades abstractas * no tienen implementaciones. Su respuesta no aborda su comentario. No hay una buena razón para que C# no permita algo como 'public string Bar {override get; conjunto privado; } ' –

7

Tal vez se vuelve más claro si se piensa en los getters y setters como los métodos en los que eventualmente se convertirán.

En el caso de la interfaz que está definiendo la siguiente:

interface IFoo 
{ 
    string GetBar(); 
} 

que se puede leer como "todas las clases que implementan esta interfaz imprescindible incluir este método." Tanto de sus clases lo hacen:

class RealFoo : IFoo 
{ 
    public string GetBar(); 
    private void SetBar(string value); 
} 

que también implementan SetBar(), pero eso es irrelevante; han cumplido el contrato definido por la interfaz y son válidos.

La clase abstracta, por el contrario es la siguiente:

abstract class AbstractFoo : IFoo 
{ 
    public abstract string GetBar(); 
} 

Lo que significa que todas las clases hijas deben proporcionar un cuerpo de método para GetBar()

La clase que se ha hecho es la siguiente:

class RealFoo : AbstractFoo 
{ 
    public override string GetBar(); 
    public override void SetBar(string value); 
} 

Al colocar el modificador de anulación por delante del método SetBar, el compilador espera encontrar una versión abstracta o virtual en la clase base. No tienes eso así que la compilación falla.

+0

Esto significa que las propiedades en realidad son solo atajos para setters y getters, y no asumen nada sobre buenos principios de oo-design. –

+2

Así que indirectamente estás diciendo que C# debería agregar sintaxis como 'public string Bar {override get; conjunto; } 'y entonces estaríamos menos arbitrariamente restringidos en la forma en que implementamos las propiedades abstractas. Eso en realidad tiene sentido. – binki

+1

@binki Tiene sentido, por lo que estas respuestas no y la restricción es arbitraria, y un diseño deficiente. C# no tiene que "agregar sintaxis", simplemente puede tomar la sintaxis proporcionada por OP y tratarla de manera inteligente, en lugar de requerirnos que proporcionemos explícitamente una variable de respaldo. –

Cuestiones relacionadas