2010-01-13 44 views
111

Quiero saber si una clase puede heredar de una clase y una interfaz. El siguiente código de ejemplo no funciona, pero creo que transmite lo que quiero hacer. La razón por la que quiero hacer esto es porque en mi empresa fabricamos dispositivos USB, seriales, Ethernet, etc. Estoy tratando de desarrollar un componente genérico/interfaz que pueda usar para escribir programas para todos nuestros dispositivos que ayuden a mantener las mismas cosas (como conectar, desconectar, obtener firmware) para todas nuestras aplicaciones.En C#, ¿puede una clase heredar de otra clase y una interfaz?

Para agregar a esta pregunta: Si GenericDevice está en proyecto diferente, ¿puedo poner la interfaz IOurDevices en ese proyecto y luego hacer que la clase USBDevice implemente la interfaz si agrego una referencia al primer proyecto? Porque me gustaría simplemente hacer referencia a un proyecto y luego implementar diferentes interfaces según el dispositivo.

class GenericDevice 
{ 
    private string _connectionState; 
    public connectionState 
    { 
     get{return _connectionState; } 
     set{ _connectionState = value;} 
    } 
} 

interface IOurDevices 
{ 
    void connectToDevice(); 
    void DisconnectDevice(); 
    void GetFirmwareVersion(); 
} 

class USBDevice : IOurDevices : GenericDevice 
{ 
    //here I would define the methods in the interface 
    //like this... 
    void connectToDevice() 
    { 
     connectionState = "connected"; 
    } 
} 

//so that in my main program I can do this... 

class myProgram 
{ 
    main() 
    { 
     USBDevice myUSB = new USBDevice(); 
     myUSB.ConnectToDevice; 
    } 
} 
+4

Para su referencia futura, la sección 10.1.4 de la especificación C# describe con precisión cómo declarar una clase que tiene múltiples tipos de bases. –

+0

@Eric Lippert: ¿Podrían por favor ayudarme a entender sobre este caso si es la forma correcta y estará disponible en el futuro? –

Respuesta

210

Sí. Proveedores:

class USBDevice : GenericDevice, IOurDevice 

Nota: clase La base debe venir antes de la lista de nombres de interfaz.

Por supuesto, igual tendrá que implementar todos los miembros que definen las interfaces. Sin embargo, si la clase base contiene un miembro que coincide con un miembro de la interfaz, el miembro de la clase base puede funcionar como la implementación del miembro de la interfaz y no es necesario que lo implemente manualmente de nuevo.

+1

¡Sí, esto funciona! ¡Por qué no pensé en eso! Y a los comentarios a continuación. Gracias por aclararme sobre eso (las clases no heredan interfaces, las interfaces IMPLEMENT) – PICyourBrain

+1

@Jordan, también tenga en cuenta que la clase base y la lista de interfaces que se heredan están separadas por comas después de los dos puntos iniciales (ejemplo de @Mehrdad) . – JMD

+1

para expandir un poco: si su clase base implementa la interfaz, su clase derivada implementa automáticamente esa interfaz, incluso sin 'USBDevice: IOurDevice'. Agregar la implementación explícitamente no afecta la clase base, pero puede ayudar a poner énfasis en la interfaz. – STW

18

No, no exactamente. Pero puede heredar de una clase y implementar una o más interfaces.

La terminología clara es importante cuando se debaten conceptos como este. Una de las cosas que verá marcar la escritura de Jon Skeet, por ejemplo, tanto aquí como impresa, es que siempre es preciso en la forma en que describe las cosas.

+8

O Eric Lippert, cuya escritura es muy precisa. – Mathias

16

relacionadas con la pregunta (respuesta de Mehrdad debe conseguir que ir), y espero que esto no se toma como nitpicky: Las clases no heredan las interfaces, que implementan ellos.

.NET no es compatible con herencia múltiple, por lo que mantener los términos correctos puede ayudar en la comunicación. Una clase puede heredar de una superclase y puede implementar tantas interfaces como desee.


Respondida a Eric's comment ...Tuve una discusión con otro desarrollador acerca de si o no las interfaces "heredan", "poner en práctica", "requiere", o "llevar consigo" las interfaces con una declaración como:

public interface ITwo : IOne 

La respuesta técnica es que ITwo qué heredan IOne por varias razones:

  • Interfaces no tienen una aplicación, por lo que el argumento de que ITwoimplementaIOne es FL en mal
  • ITwo hereda IOne métodos, si existe MethodOne() en IOne entonces también es accesible desde ITwo. es decir: ((ITwo)someObject).MethodOne()) es válido, aunque ITwo no contiene explícitamente una definición para MethodOne()
  • ... ¡porque el tiempo de ejecución lo dice! typeof(IOne).IsAssignableFrom(typeof(ITwo)) devuelve true

Finalmente, aceptamos que las interfaces son compatibles con la herencia verdadera/completa. Las características de herencia faltantes (como anulaciones, accesos abstractos/virtuales, etc.) faltan en las interfaces, no en la herencia de la interfaz. Todavía no hace que el concepto sea simple o claro, pero ayuda a comprender lo que sucede realmente en el mundo de Eric :-)

+2

Aunque, desafortunadamente, las interfaces * heredan * otras interfaces. Encuentro esa elección de palabras desafortunada, pero estamos atrapados con eso ahora. Prefiero pensar que las interfaces requieren * otras interfaces.Es decir, cuando dices "interfaz IFoo: IBar" eso significa que "se requiere que un implementador de IFoo también implemente IBar". –

+0

@Eric Estoy de acuerdo en que es un término poco claro y lo debatí con un colega hace un tiempo. Al final decidimos que decir "ITwo hereda IOne". Actualizaré mi respuesta con un par de pequeñas razones (solo porque no encajarán claramente en un comentario). – STW

+0

Sure; si define "A hereda de B" como "los miembros de B son todos miembros de A", entonces las interfaces "heredan" de las interfaces base. Esta es una definición razonable. Pero prefiero pensar que la "herencia" es más estrictamente no solo de compartir los miembros abstractos y no implementados, sino de heredar * implementaciones *. Dado que las interfaces no tienen implementaciones, me resulta un tanto inquietante pensar que las interfaces heredan de cualquier cosa. Es un punto sutil y discutible. –

1

Encontré la respuesta a la segunda parte de mis preguntas. Sí, una clase puede implementar una interfaz que está en una clase diferente siempre que la interfaz se declare como pública.

+0

No tiene que ser público en todos los casos. Solo accesible. Por ejemplo 'clase ContainsAll {private interface INested {/ * ... * /} private class MyExample: INested {/ * ... * /}}', la clase 'MyExample' implementa una interfaz privada anidada. En otros ejemplos, la interfaz anidada (y la clase contenedora) podría ser 'interna'. Todo depende de quién necesita usarlos y molestarse con ellos. –

Cuestiones relacionadas