2010-01-13 11 views
111

Voglio sapere se una classe può ereditare da una classe e un'interfaccia. Il codice di esempio qui sotto non funziona, ma penso che trasmetta ciò che voglio fare. Il motivo per cui voglio farlo è perché nella mia azienda realizziamo dispositivi USB, seriali, Ethernet, ecc. Sto cercando di sviluppare un componente/interfaccia generico che possa essere utilizzato per scrivere programmi per tutti i nostri dispositivi che contribuirà a mantenere le stesse cose comuni (come la connessione, la disconnessione, il recupero del firmware) per tutte le nostre applicazioni.In C#, una classe può ereditare da un'altra classe e un'interfaccia?

Per aggiungere a questa domanda: Se GenericDevice si trova in un progetto diverso, posso inserire l'interfaccia IOurDevices in quel progetto, quindi rendere la classe USBDevice implementare l'interfaccia se aggiungo un riferimento al primo progetto? Perché vorrebbe solo fare riferimento a un progetto e quindi implementare interfacce diverse a seconda del 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

Per riferimento futuro, la sezione 10.1.4 della specifica C# descrive esattamente come dichiarare una classe che ha più tipi di base. –

+0

@Eric Lippert: Potresti per favore aiutarmi a capire su questo caso se è corretto e sarà disponibile in futuro? –

risposta

210

Sì. Prova:

class USBDevice : GenericDevice, IOurDevice 

Nota: classe La base dovrebbe venire prima l'elenco dei nomi di interfaccia.

Naturalmente, sarà comunque necessario implementare tutti i membri definiti dalle interfacce. Tuttavia, se la classe base contiene un membro che corrisponde a un membro dell'interfaccia, il membro della classe base può funzionare come implementazione del membro dell'interfaccia e non è necessario implementarlo nuovamente manualmente.

+1

Sì, funziona! Perché non ci ho pensato! E ai commenti qui sotto. Grazie per avermi chiarito (le Classi non ereditano le interfacce, le interfacce IMPLEMENT) – PICyourBrain

+1

@Jordan, si noti inoltre che la classe base e l'elenco delle interfacce ereditate sono separate da virgole dopo i due punti iniziali (l'esempio di @ Mehrdad) . – JMD

+1

per espandere solo un po ': se la vostra classe base implementa l'interfaccia, la vostra classe derivata implementa automaticamente tale interfaccia, anche senza 'USBDevice: IOurDevice'. Aggiungere esplicitamente l'implementazione non ha alcun impatto sulla classe base, ma può aiutare a porre l'accento sull'interfaccia. – STW

18

No, non esattamente. Ma può ereditare da una classe e implementare una o più interfacce.

La terminologia chiara è importante quando si discutono concetti come questo. Una delle cose che vedrai segnare la sceneggiatura di Jon Skeet, ad esempio, sia qui che in stampa, è che è sempre preciso nel modo in cui decifra le cose.

+8

Oppure Eric Lippert, la cui scrittura è molto accurata. – Mathias

16

estraneo alla domanda (risposta di Mehrdad dovrebbe farti andare), e spero che questo non è preso come nitpicky: classi non erediti interfacce, che implementano loro.

.NET non supporta l'ereditarietà multipla, quindi mantenere i termini può aiutare nella comunicazione. Una classe può ereditare da una superclasse e può implementare tutte le interfacce che desidera.


In risposta al commento di Eric ...Ho avuto una discussione con un altro sviluppatore circa o meno interfacce "ereditano", "attuare", "richiede", o "portare" le interfacce con una dichiarazione del tipo:

public interface ITwo : IOne 

La risposta tecnica è che ITwo fa ereditano IOne per alcuni motivi:

  • Interfacce mai hanno un'implementazione, in modo sostenendo che ITwoimplementaIOne è FL a torto
  • ITwo eredita IOne metodi, se MethodOne() esiste su IOne, allora è anche accessibile da ITwo. vale: ((ITwo)someObject).MethodOne()) è valido, anche se ITwo non contiene esplicitamente una definizione per MethodOne()
  • ... perché il runtime lo dice! typeof(IOne).IsAssignableFrom(typeof(ITwo)) rendimenti true

Abbiamo finalmente convenuto che supportano interfacce vera eredità/pieno. Le caratteristiche di ereditarietà mancanti (come override, accessors astratti/virtuali, ecc.) Mancano dalle interfacce, non dall'ereditarietà dell'interfaccia. Ancora non rende il concetto semplice o chiaro, ma aiuta a capire cosa sta veramente succedendo nel mondo di Eric :-)

+2

Sebbene, purtroppo, le interfacce * ereditano * altre interfacce. Trovo sfortunata questa scelta di parole, ma ora siamo bloccati. Preferisco pensare alle interfacce come * richiedendo * altre interfacce.Cioè, quando dici "interfaccia IFoo: IBar" che significa "un implementatore di IFoo è richiesto anche per implementare IBar". –

+0

@Eric Sono d'accordo che non è chiaro e lo discuto con un collega qualche tempo fa. Alla fine abbiamo deciso di dire "ITwo eredita IOne". Aggiornerò la mia risposta con un paio di piccoli motivi (solo perché non si inseriranno chiaramente in un commento). – STW

+0

Sicuro; se si definisce "A inherits from B" nel senso che "i membri di B sono tutti membri di A", le interfacce "ereditano" dalle interfacce di base. Questa è una definizione ragionevole. Ma preferisco pensare alla "ereditarietà" più strettamente non solo alla condivisione dei membri astratti non implementati, ma piuttosto al fatto di ereditare * le implementazioni *. Poiché le interfacce non hanno implementazioni, trovo alquanto inquietante pensare che le interfacce ereditino da qualsiasi cosa. È un punto sottile e discutibile. –

1

Ho trovato la risposta alla seconda parte delle mie domande. Sì, una classe può implementare un'interfaccia che si trova in una classe diversa finché l'interfaccia è dichiarata pubblica.

+0

Non deve essere pubblico in tutti i casi. Semplicemente accessibile Ad esempio 'class ContainsAll {interfaccia privata INested {/ * ... * /} classe privata MyExample: INested {/ * ... * /}}', la classe 'MyExample' implementa un'interfaccia privata nidificata. In altri esempi, l'interfaccia nidificata (e la classe contenente) potrebbe essere 'internal'. Tutto dipende da chi ha bisogno di usarli e preoccuparsi di loro. –

Problemi correlati