Por ejemplo, supongamos que quiero una ICar
interfaz y que todas las implementaciones contendrán el campo Year
. ¿Esto significa que cada implementación tiene que declarar por separado Year
? ¿No sería mejor simplemente definir esto en la interfaz?
223
Respuestas:
Aunque muchas de las otras respuestas son correctas a nivel semántico, también me parece interesante abordar este tipo de preguntas desde el nivel de detalles de implementación.
Una interfaz puede considerarse como una colección de ranuras , que contienen métodos . Cuando una clase implementa una interfaz, se requiere que la clase le diga al tiempo de ejecución cómo completar todos los espacios requeridos. Cuando tu dices
la clase dice "cuando creas una instancia de mí, escribe una referencia a Foo.M en el espacio para IFoo.M.
Luego, cuando haces una llamada:
el compilador genera un código que dice "pregunte al objeto qué método hay en la ranura para IFoo.M, y llame a ese método.
Si una interfaz es una colección de ranuras que contienen métodos, entonces algunas de esas ranuras también pueden contener los métodos get y set de una propiedad, los métodos get y set de un indexador y los métodos add y remove de un evento. Pero un campo no es un método . No hay un "espacio" asociado con un campo que luego pueda "completar" con una referencia a la ubicación del campo. Y, por lo tanto, las interfaces pueden definir métodos, propiedades, indexadores y eventos, pero no campos.
fuente
An interface cannot contain constants, fields, operators
De. msdn.microsoft.com/en-us/library/ms173156.aspx )int One()
, entonces la implementaciónpublic int One(){return 1;}
no es un campo.Las interfaces en C # están destinadas a definir el contrato al que se adherirá una clase, no una implementación particular.
En ese espíritu, las interfaces de C # permiten que se definan propiedades, que la persona que llama debe proporcionar una implementación para:
Las clases de implementación pueden usar propiedades automáticas para simplificar la implementación, si no hay una lógica especial asociada con la propiedad:
fuente
Year
?public int Year => 123;
. Sin embargo, en este caso no tiene sentido tener un setter, por lo que la interfaz debería definirse conint Year { get; }
Declararlo como una propiedad:
fuente
Eric Lippert lo clavó, usaré una forma diferente de decir lo que dijo. Todos los miembros de una interfaz son virtuales y todos deben ser anulados por una clase que herede la interfaz. No escribe explícitamente la palabra clave virtual en la declaración de la interfaz, ni utiliza la palabra clave de anulación en la clase, están implícitas.
La palabra clave virtual se implementa en .NET con métodos y una denominada v-table, una matriz de punteros de métodos. La palabra clave override llena el espacio de la tabla v con un puntero de método diferente, sobrescribiendo el producido por la clase base. Las propiedades, los eventos y los indexadores se implementan como métodos subyacentes. Pero los campos no lo son. Por lo tanto, las interfaces no pueden contener campos.
fuente
¿Por qué no simplemente tener una
Year
propiedad, que está perfectamente bien?Las interfaces no contienen campos porque los campos representan una implementación específica de representación de datos, y exponerlos rompería la encapsulación. Por lo tanto, tener una interfaz con un campo sería una codificación efectiva para una implementación en lugar de una interfaz, ¡lo cual es una paradoja curiosa para una interfaz!
Por ejemplo, parte de su
Year
especificación podría requerir que no sea válido para losICar
implementadores permitir la asignación a un añoYear
posterior al año actual + 1 o anterior a 1900. No hay forma de decir que si hubiera expuestoYear
campos, es mucho mejor usar propiedades en lugar de hacer el trabajo aquí.fuente
La respuesta corta es sí, cada tipo de implementación tendrá que crear su propia variable de respaldo. Esto se debe a que una interfaz es análoga a un contrato. Todo lo que puede hacer es especificar partes particulares de código de acceso público que un tipo de implementación debe poner a disposición; no puede contener ningún código en sí mismo.
Considere este escenario usando lo que sugiere:
Tenemos un par de problemas aquí:
myBackingVariable
va aMyClass
usar?El enfoque más común adoptado es declarar la interfaz y una clase abstracta básica que la implementa. Esto le permite la flexibilidad de heredar de la clase abstracta y obtener la implementación de forma gratuita, o implementar explícitamente la interfaz y se le permite heredar de otra clase. Funciona algo como esto:
fuente
Otros han dado el 'Por qué', así que solo agregaré que su interfaz puede definir un Control; si lo envuelve en una propiedad:
fuente
Las interfaces no contienen ninguna implementación.
fuente
Ya se ha dicho mucho, pero para simplificar, aquí está mi opinión. Las interfaces tienen la intención de tener contratos de métodos para ser implementados por los consumidores o clases y no tener campos para almacenar valores.
Puede argumentar que entonces ¿por qué se permiten las propiedades? Entonces, la respuesta simple es: las propiedades se definen internamente solo como métodos.
fuente
Para esto, puede tener una clase base Car que implemente el campo año, y todas las demás implementaciones pueden heredar de él.
fuente
Una interfaz define propiedades y métodos de instancia pública . Los campos son generalmente privados, o como máximo protegidos, internos o internos protegidos (el término "campo" generalmente no se usa para nada público).
Como se indica en otras respuestas, puede definir una clase base y definir una propiedad protegida a la que puedan acceder todos los herederos.
Una rareza es que, de hecho, una interfaz puede definirse como interna, pero limita la utilidad de la interfaz, y normalmente se usa para definir la funcionalidad interna que no utiliza otro código externo.
fuente