Pregunta

Considera esto:

public class interface Person : IPerson
{
  int ID { get; protected set; }
  string FirstName { get; set; }
  string LastName { get; set; }
  string FullName { get { return FirstName + " " + LastName; } }
}

Y esto:

public class StubPerson : IPerson
{
    int ID { get { return 0; protected set { } }
    string FirstName { get { return "Test" } set { } }
    string LastName { get { return "User" } set { } }
    string FullName { get { return FirstName + " " + LastName; } }
}

Uso:

IPerson iperson = new Person();

O:

IPerson ipersonStub = new StubPerson();

O:

IPerson ipersonMock = mocks.CreateMock<IPerson>();

Entonces, en efecto, estamos declarando la interfaz IPerson y la clase Persona al mismo tiempo:

public class interface Person : IPerson

¿Crees que sería útil tener este tipo de soporte en .NET / C #?

Edición :

Debido a la confusión masiva, creo que necesito aclarar el propósito propuesto:

Sin esta función, tendría que escribir:

interface IPerson
{
  int ID { get; }
  string FirstName { get; set; }
  string LastName { get; set; }
  string FullName { get; }
}

además de esto:

public class Person : IPerson
{
  int ID { get; protected set; }
  string FirstName { get; set; }
  string LastName { get; set; }
  string FullName { get { return FirstName + " " + LastName; } }
}

No estoy proponiendo ningún cambio semántico en absoluto.

¿Fue útil?

Solución

Considere el el mismo tipo de cosas hace un tiempo , particularmente para su uso en el caso en que solo tiene una implementación de producción de una interfaz, pero desea simularla para probarla. Por el momento, termina siendo un poco como los archivos .c / .h de antaño.

Sospecho que al final los beneficios de esto se ven compensados ??por la complejidad adicional tanto en el lenguaje como en la lectura del código. Sin embargo, todavía estaría interesado en verlo explorado más a fondo. Incluso entonces, hay otras cosas mucho más altas en mi lista de prioridades: mejor soporte para la inmutabilidad al estar en la parte superior :)

Otros consejos

Déjame ver si entiendo lo que estás preguntando:

¿Por qué no podemos declarar una interfaz?

interface IPerson
{
    string Name {get;set;}
    int ID {get;set;}
}

Y las clases que implementan esa interfaz heredarán sus propiedades sin tener que volver a declararlas:

class Person : IPerson { } 
//person now has properties Name and ID

La razón por la que no puede hacer esto es que aunque el texto de su código de interfaz y su código de clase son muy similares, significan muy cosas diferentes. La interfaz simplemente dice "el implementador tendrá un nombre de cadena con getter y setter". Es la clase que dice "devolver campo privado cuando se invoca getter for name". Incluso si utiliza el acceso directo de propiedad automática para permitir que el compilador implemente esa lógica, sigue siendo lógica , que pertenece a la clase. Solo porque:

string Name {get;set;}

se ve igual en una interfaz y en una clase, no significa ni remotamente lo mismo.

Sería muy peligroso para el compilador implementar una lógica arbitraria para cumplir con sus contratos por usted, en lugar de quejarse en el momento de la compilación de que no los ha implementado. Podría introducir errores muy difíciles de rastrear. Hacer que los compiladores vuelvan al comportamiento predeterminado cuando no se define ningún comportamiento es una muy, muy mala idea.

Creo que Eiffel hace algo así en .NET para admitir la herencia múltiple. Una declaración de clase produce automáticamente una interfaz correspondiente. Cuando se hace referencia al tipo de clase, el compilador emite principalmente una referencia al tipo de interfaz. La principal excepción está en las expresiones de constructor, por supuesto.

Bueno, creo que las otras respuestas lo ayudarán a comprender el uso de la interfaz para abstraer la lógica en diferentes clases concretas, también creo que puede lograr algo similar a lo que desea utilizando las herramientas de refactorización integradas en VS.

Define tu clase ...

public class Person
{
  public int ID { get; protected set; }
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string FullName { get { return FirstName + " " + LastName; } }
}

Luego haga clic derecho, seleccione Refactor - > Extraer interfaz.

Esto creará un archivo separado que contiene la interfaz para la definición de la clase, luego podría moldear la interfaz e implementar las clases en consecuencia.

Interfaz extraída:

interface IPerson
{
    string FirstName { get; set; }
    string FullName { get; }
    int ID { get; }
    string LastName { get; set; }
}

Supongo que me estoy perdiendo el punto: ¿qué estás logrando al mezclar una clase y una interfaz? ¿Qué problema estás resolviendo con este enfoque?

Esto:

IPerson iperson = new Person();

ya es legal en C #.

Editar: Para aclaración, el código anterior es legal dado lo siguiente:

interface IPerson { }

class Person : IPerson { }

Al menos me gustaría que Visual Studio implemente mis propiedades desde una interfaz como propiedades automáticas si así lo solicito.

Desafortunadamente, esta opción no funciona y tengo que tratar con trozos de excepción no implementados

No, porque se vería obligado a exponer a todos los miembros públicos de una interfaz. Pruebe ReSharper , y nunca más se preocupe por esto.

Resharper puede proporcionar esta funcionalidad, por ejemplo,

  1. Puedes escribir tu clase de Persona primero.
  2. Puede extraer su interfaz levantando miembros hacia el Interfaz IPerson.

En consecuencia, puede tener los resguardos de implementación de generación automática de Visual Studio para usted.

UPDATE

De todos modos, expongamos primero las interfaces, citando el código que proporcionó en su pregunta:

public class interface Person : IPerson
{
    int ID { get; protected set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    string FullName { get { return FirstName + " " + LastName; } }
}

Debe comprender que una interfaz no es una clase abstracta. Una interfaz es simplemente un contrato , una especie de plano, lo que significa que le dirá a un objeto qué esperar en otro objeto sin preocuparse realmente por cómo se implementa.

Una clase abstracta, por otro lado, puede contener fragmentos de funcionalidad que se pueden heredar y anular.

En el caso anterior, su " interfaz " no es válido porque:

  • no puede declarar restricciones de alcance en las interfaces (públicas, privadas, protegidas, internas) ya que es un detalle de implementación
  • no pudo declarar una implementación predeterminada (por ejemplo, su propiedad FullName ) porque, de nuevo, eso es un detalle de implementación

Me parece que lo que realmente quieres es una clase abstracta, por ejemplo,

public abstract class BasePerson
{
    public abstract int ID { get; protected set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public virtual string FullName { get { return FirstName + " " + LastName; } } 
}

Solo estoy adivinando, pero tal vez eso es lo que realmente necesitas.

ACTUALIZACIÓN 2

Bien, creo que estoy entendiendo lo que quieres que suceda, así que lo que quieres es poder escribir esto:

public interface IPerson
{
    int ID { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
    string FullName { get; }
}

Y luego para su implementación solo necesita escribir esto:

public class Person : IPerson
{
    public int ID { get; protected set; }
    public string FullName { get { return FirstName + " " + LastName; } } 
}

Sin necesidad de especificar las propiedades FirstName y LastName.

El primer problema que debemos abordar es el hecho de que las interfaces no permiten delimitadores de acceso en su implementación: lo que sucedería es que las propiedades heredarían el delimitador de acceso predeterminado, que es privado.

El segundo es el hecho de que, a nuestro juicio, string FirstName {get; conjunto; } en una interfaz y cadena pública FirstName {get; conjunto; } en una clase son iguales, en realidad no lo son:

  • en una interfaz, la definición de propiedad indicará que las firmas de métodos para los métodos getter y / o setter estarán disponibles para todas las clases que implementen esa interfaz.
  • en una clase, la definición de propiedad indicará al CLR que cree un objeto anónimo que contendrá el valor de dicha propiedad.

Diferencia sutil para el programador, un mundo aparte para el compilador.

Por último, cuando especificas que estás implementando una interfaz, Visual Studio realiza magia sintáctica que automáticamente crea esos resguardos de propiedades para ti.

Creo que una mejor abstracción para esto es un rasgo, o, como he descrito, aquí , un rol. Esto es como una interfaz con código. Su ejemplo podría codificarse así:

public role RPerson { 
  int ID { get; protected set; } 
  string FirstName { get; set; } 
  string LastName { get; set; } 
  string FullName { get { return FirstName + " " + LastName; } } 
} 

public class Person : RPerson { }

public class StubPerson : RPerson { 
    int ID { get { return 0; protected set { } } 
    string FirstName { get { return "Test" } set { } } 
    string LastName { get { return "User" } set { } } 
    string FullName { get { return FirstName + " " + LastName; } } 
} 

// ...

RPerson rperson = new Person(); 

RPerson rpersonStub = new StubPerson(); 
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top