it-swarm-es.tech

¿Por qué las interfaces de C # no pueden contener campos?

Por ejemplo, supongamos que quiero una interfaz ICar y que todas las implementaciones contendrán el campo Year. ¿Significa esto que cada implementación debe declarar por separado Year? ¿No sería mejor simplemente definir esto en la interfaz?

207
deltanovember

Aunque muchas de las otras respuestas son correctas a nivel semántico, me parece interesante abordar también este tipo de preguntas desde el nivel de detalles de implementación.

Una interfaz se puede considerar como una colección de slots , que contiene métodos . Cuando una clase implementa una interfaz, se requiere que la clase le diga al tiempo de ejecución cómo completar todas las ranuras requeridas. Cuando tu dices

interface IFoo { void M(); } 
class Foo : IFoo { public void M() { ... } }

la clase dice "cuando crees una instancia de mí, rellena una referencia a Foo.M en la ranura para IFoo.M.

Entonces cuando haces una llamada:

IFoo ifoo = new Foo();
ifoo.M();

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, algunas de esas ranuras también pueden contener los métodos de obtención y configuración de una propiedad, los métodos de obtención y configuración de un indexador y los métodos de adición y eliminación de un evento. Pero un campo no es un método . No hay una "ranura" asociada con un campo que luego puede "rellenar" 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.

224
Eric Lippert

Las interfaces en C # están destinadas a definir el contrato al que se adherirá una clase, no una implementación en particular.

En ese sentido, C # interfaces permite que se definan propiedades, para las cuales el llamante debe proporcionar una implementación para:

interface ICar
{
    int Year { get; set; }
}

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:

class Automobile : ICar
{
    public int Year { get; set; } // automatically implemented
}
125
LBushkin

Declararlo como una propiedad:

interface ICar {
   int Year { get; set; }
}
48
Tarydon

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 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 la llamada v-table, una matriz de punteros a métodos. La palabra clave de anulación llena la ranura de la v-table con un puntero de método diferente, sobrescribiendo el producido por la clase base. Las propiedades, eventos e indexadores se implementan como métodos bajo el capó. Pero los campos no lo son. Por lo tanto, las interfaces no pueden contener campos.

34
Hans Passant

¿Por qué no tener una propiedad Year, que está perfectamente bien?

Las interfaces no contienen campos porque los campos representan una implementación específica de la representación de datos, y su exposición podría interrumpir la encapsulación. Por lo tanto, tener una interfaz con un campo sería efectivamente codificar para una implementación en lugar de una interfaz, ¡lo cual es una curiosa paradoja para una interfaz!

Por ejemplo, parte de su especificación de Year puede requerir que no sea válida para los implementadores de ICar para permitir la asignación a un Year que es posterior al año actual + 1 o antes de 1900. No hay manera de decir que si ha expuesto Year campos - Mucho mejor usar propiedades en lugar de hacer el trabajo aquí.

19
John Feminella

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 piezas 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í.

Considere este escenario usando lo que sugiere:

public interface InterfaceOne
{
    int myBackingVariable;

    int MyProperty { get { return myBackingVariable; } }
}

public interface InterfaceTwo
{
    int myBackingVariable;

    int MyProperty { get { return myBackingVariable; } }
}

public class MyClass : InterfaceOne, InterfaceTwo { }

Aquí tenemos un par de problemas:

  • Debido a que todos los miembros de una interfaz son, por definición, públicos, nuestra variable de respaldo ahora está expuesta a cualquiera que use la interfaz
  • ¿Qué myBackingVariable usará MyClass?

El enfoque más común adoptado es declarar la interfaz y una clase abstracta de barebones 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:

public interface IMyInterface
{
    int MyProperty { get; set; }
}

public abstract class MyInterfaceBase : IMyInterface
{
    int myProperty;

    public int MyProperty
    {
        get { return myProperty; }
        set { myProperty = value; }
    }
}
17
Adam Robinson

Otros han dado el 'Por qué', así que solo agregaré que su interfaz puede definir un Control; Si lo envuelves en una propiedad:

public interface IView {
    Control Year { get; }
}


public Form : IView {
    public Control Year { get { return uxYear; } } //numeric text box or whatever
}
5
zomf

Las interfaces no contienen ninguna implementación.

  1. Definir una interfaz con una propiedad.
  2. Además, puede implementar esa interfaz en cualquier clase y usar esta clase en el futuro.
  3. Si es necesario, puede tener esta propiedad definida como virtual en la clase para que pueda modificar su comportamiento.
3
Amit

Ya se ha dicho mucho, pero para simplificarlo, aquí está mi opinión. Las interfaces están destinadas a tener contratos de método para ser implementados por los consumidores o clases y no tener campos para almacenar valores.

Puedes argumentar que entonces ¿por qué se permiten las propiedades? Así que la respuesta simple es: las propiedades se definen internamente solo como métodos.

2
Prakash Tripathi

Una interfaz define las propiedades y métodos de public instance. Los campos son típicamente privados, o en la mayoría de los casos protegidos, internos o protegidos internos (el término "campo" generalmente no se usa para nada público).

Como lo indican otras respuestas, puede definir una clase base y una propiedad protegida a la que podrán acceder todos los herederos.

Una rareza es que, de hecho, una interfaz se puede definir como interna pero limita la utilidad de la interfaz, y generalmente se usa para definir una funcionalidad interna que no es utilizada por otro código externo.

0
Frode N. Rosand

Para esto, puede tener una clase base de Automóvil que implemente el campo del año, y todas las demás implementaciones pueden heredar de él.

0
IK