2012-09-17 11 views
18

me encontré con una interfaz recientemente que sólo se define un pionero de este modo:Interfaz: Setter sin Getter

public interface IAggregationView 
{ 
    DataTable SetSiteData { set; } 
} 

He preguntado, y se cree que esta es una de las prácticas promovidas por Microsoft para su WebPart diseño (para SharePoint). De hecho, este ejemplo se copia directamente de sus ejemplos.

Veo esto como un mal patrón, no veo por qué alguien debería ser capaz de establecer un valor, y luego no ser capaz de leerlo nuevamente, y creo que un setter siempre debe ir acompañado de un getter (pero no necesariamente al revés).

Me pregunto si alguien puede explicar el beneficio de solo tener un colocador, por qué Microsoft podría sugerirlo en este caso, y si realmente es un buen patrón para seguir?

+0

yo supongo que es lo mismo que no proporciona una incubadora. El colocador en ese caso es un conjunto privado por defecto. Probablemente lo mismo para el getter también. –

+4

Si no duplica a continuación, puede estar relacionada: http://stackoverflow.com/questions/4695551/write-only-properties-whats-the-point – Habib

+1

Es un patrón inusual, sin duda; como está nombrando una propiedad con un prefijo 'Set ...'. –

Respuesta

20

Hay dos escenarios puedo ver que esto podría ser razonable:

  1. no es posible obtener el valor, por ejemplo, una contraseña; Sin embargo, me gustaría sustituir a un método void SetPassword(string), personalmente
  2. la API está diseñado para no tiene ningún requisito para leer cada vez el valor, y está siendo restringida exclusivamente para exponer el mínimo requerido API

En mi primer punto, un Set...método puede no ser ideal si la API que consume es esencialmente un asignador automatizado que asigna valores a las propiedades; en ese escenario las propiedades serían de hecho preferibles.

Re your "No veo por qué alguien debería ser capaz de establecer un valor, y luego no ser capaz de leerlo de nuevo" - por el mismo punto, sin embargo, podría argumentarse que alguien establezca el valor ya conoce el valor (lo configuraron), por lo que no tienen requisito para hacer esto.

Pero sí; es muy inusual tener una propiedad de solo conjunto.

+0

Me gusta su ejemplo de contraseña en realidad, es un buen caso claro de dónde podría querer hacer esto, pero personalmente también optaría por un método. Buena respuesta. – Ian

+0

Si espera que al menos algunas clases implementadoras agreguen un getter, entonces tiene sentido tenerlo como un setter en lugar de un método 'SetFoo'. Las interfaces no son independientes, representan un subconjunto común de las operaciones en una familia de clases. Por lo tanto, debe considerar las clases existentes, así como también el código que consume las interfaces, para decidir si el diseño de la interfaz tiene sentido. –

+0

@DanielEarwicker sí, pero cuando la API de interfaz no es un subconjunto de la API pública directa de la clase, siempre hay * implementación de interfaz explícita * –

1

En mi experiencia, tales interfaces surgen debido a alguna necesidad especial, no por razones arquitectónicas. Por ejemplo, en las aplicaciones ASP.NET las personas a veces hacen que el tipo generado por Global.asax derive de dicha interfaz cuando quieren mantener el estado global. Alguien puede crear un valor de inicialización en una parte separada de la aplicación y necesita publicarlo en un lugar global.

Normalmente me gusta reemplazar una propiedad de solo conjunto con un método SetXxx y hacer que el método compruebe que se llame como máximo una vez. De esa manera, claramente hago cumplir el "estilo de inicialización" que es mucho menos un olor (imho).

Ciertamente no se puede establecer en Nunca produce tal cosa, pero debe evitarse y sin duda planteará preguntas durante la revisión del código.

2

Las clases que implementan la interfaz pueden agregar un getter. La mayoría de los usos de la propiedad pueden ser a través de una clase de implementación, no a través de la interfaz en sí. En cuyo caso, la mayoría del código tiene la capacidad de obtener y establecer la propiedad. La única razón para la interfaz puede ser que haya algún código común que acceda a un subconjunto común de los métodos/propiedades de una familia de clases. Ese código solo requiere el colocador, no el captador. La interfaz documenta ese hecho.

Una interfaz es solo una facilidad para declarar un grupo de operaciones que son "atómicamente necesarias" (por ejemplo, si necesita llamar al método A, necesitará leer la propiedad B y establecer la propiedad C).

Como siempre, depende.

14

La función de get y set en las propiedades de la interfaz es ligeramente diferente de las de las clases.

public interface IAggregationView 
{ 
    DataTable SetSiteData { set; } 
} 

class AggregationViewImp : IAggregationView 
{ 
    public DataTable SetSiteData { get; set; } // perfectly OK 
} 

La interfaz especifica que la propiedad debe al menos tener un colocador pública. La definición y accesibilidad del getter se deja a la clase implementadora.

lo tanto, si el contrato interfaz sólo tiene que escribir, get puede dejarse abierta. No es necesario exigir un getter público.

Como consecuencia de ello, realmente no se puede especificar una propiedad de sólo lectura en las interfaces tampoco. Solo 'al menos acceso de lectura'.

interface IFoo 
{ 
    int Id { get; } 
} 

class Foo : IFoo 
{ 
    public int Id { get; set; } // protected/private set is OK too 
} 
+0

+1 más elocuente que el mío, y con ejemplos de código. –

+0

Igualmente importante es que "Foo" es * interno *, lo que encapsula adecuadamente la implementación dentro de su alcance inmediato. –

4

Me imagino usarlo para inyección de dependencia (manual). Una clase puede necesitar tener un colaborador inyectado que solo use internamente. Por supuesto, uno normalmente elegiría hacer esto en el constructor de la clase, pero puede haber ocasiones en las que uno desearía cambiar el colaborador en el tiempo de ejecución.

Cuestiones relacionadas