C'è qualche differenza tra interfacce e classi astratte che hanno solo metodi astratti?


9

Diciamo che abbiamo una classe astratta e lasciamo che questa classe abbia solo metodi astratti. Questa classe astratta è diversa da un'interfaccia che ha solo gli stessi metodi?

Quello che sto cercando di sapere è se ci sono differenze sia filosoficamente, obiettivamente e nell'implementazione del linguaggio di programmazione sottostante tra una classe astratta con solo membri astratti e un'interfaccia equivalente?


quale lingua?
Kevin Cline,

per quanto ne so, la tua domanda si risponde in duplicato due volte : qui e qui . E queste due risposte sono agnostiche del linguaggio, niente di specifico per C # lì
moscerino del

3
@blank Non sono d'accordo con lo stato Duplicato applicato alla tua domanda, quindi l'ho riaperto. Inoltre ho modificato la tua domanda per chiarire ulteriormente ciò che credo stiate chiedendo.
maple_shaft

Risposte:


22

Tecnicamente, le differenze non sono davvero significative ma, concettualmente, sono cose completamente diverse e questo porta alle differenze tecniche che altri hanno menzionato.

Una superclasse astratta è esattamente ciò che sembra, è un tipo comune che è condiviso da molti altri tipi, come Cats and Dogs are Animals.

Un'interfaccia è anche esattamente come sembra, è un'interfaccia attraverso la quale altre classi possono comunicare con l'oggetto. Se vuoi fare una passeggiata Cat, stai bene, perché Cat implementa un'interfaccia CanWalk. Lo stesso vale per una lucertola, sebbene camminino in modo molto diverso. Un Snake, d'altra parte, non implementa CanWalk, quindi non puoi dirlo a Walk. Nel frattempo, Lizard e Snake (o forse sottoclassi più esplicite - non sono un esperto) potrebbero entrambi perdere la pelle e quindi implementare CanShed, mentre un gatto non può farlo.

Ma sono tutti ancora animali e hanno alcune proprietà comuni, come se siano vivi o morti.

Questo è il motivo per cui tutti i metodi su un'interfaccia devono essere implementati come pubblici (o esplicitamente, in C #). Perché qual è il punto in un'interfaccia nascosta dalla classe che si interfaccia con l'oggetto? È anche il motivo per cui è possibile avere più interfacce per un oggetto, anche quando una lingua non supporta l'ereditarietà multipla.

Per tornare alla tua domanda, quando la guardi in questo modo, molto raramente c'è un motivo per avere una superclasse completamente astratta.


4
+1, sebbene i gatti perdano in modo molto più fastidioso di serpenti o lucertole.
Matthew Flynn,

Tecnicamente: i metodi astratti possono essere protetti. Metodi di interfaccia cant.
Jacques Koorts,

19

Nella maggior parte dei linguaggi OOP, una classe di implementazione può derivare solo da una classe astratta, ma implementare più interfacce.


3
maggior parte? quali stai contando? La maggior parte dei linguaggi OOP che conosco non ha interfacce o classi astratte. C ++ ha solo classi astratte.
Kevin Cline,

10
@kevincline: probabilmente C #, Java e VB.NET.
martedì

1
@kevincline, penso che manchi solo un "avere entrambi". IIRC, in Ada la motivazione per l'interfaccia era quella, i progettisti non volevano una caratteristica di ereditarietà multipla generale ma il caso speciale di interfaccia era ritenuto troppo importante per non essere fornito.
Approgrammatore

@tdammers: LOL. Quello era uno scherzo, vero?
Kevin Cline,

3

In un linguaggio come C ++ che consente l'ereditarietà multipla e non ha interfacce, le classi astratte in cui tutti i metodi sono astratti possono fungere da interfacce. Non ho lavorato molto con C ++, ma immagino che l'ereditarietà multipla possa causare problemi quando ci sono metodi con lo stesso nome nelle classi di base.

In linguaggi come PHP e C #, le interfacce forniscono un mezzo per ottenere un polimorfismo simile, anche se non mi piace chiamarlo "eredità" poiché esiste una differenza concettuale tra ereditare una classe astratta e implementare un'interfaccia. Le interfacce rimuovono il problema del conflitto, poiché esse non forniscono alcuna implementazione.

Un'interfaccia funge da contratto con il mondo esterno, mentre una classe astratta può fornire un'implementazione, sebbene se usata per "falsificare" un'interfaccia, molto probabilmente non lo farà.

La principale differenza concettuale è che quando una classe eredita un'altra classe (astratta o no), c'è una relazione di "is", quindi a Caris a Vehicleed Dogis an Animal. Con un'interfaccia, è ciò che fa l'oggetto che conta. Così sia Care Dogpuò Move()e il consumatore lo sa perché implementano Movable, ma una macchina non è sicuramente una Dog, o un Animal. E l'implementazione delle mosse sarà diversa (ruote contro gambe) ma il codice consumante non è e non dovrebbe interessarsene. Le interfacce riguardano il consumo di codice, piuttosto che l'implementazione.

Il punto principale è se hai interfacce nella tua lingua preferita, usale per cose per cui sono lì. Altrimenti (come in C ++), puoi falsificarli usando classi astratte pure.


Interface è un tipo così, così si potrebbe avere un IAnimal cui entrambi Doge Cat sei .
Amy Blankenship,

Potresti, ma a mio avviso, le interfacce riguardano il comportamento che è esposto al mondo esterno e non tanto quello che sono gli oggetti. L'ereditarietà implica che qualcosa è un tipo di qualcos'altro (Cat is an Animal). Un'interfaccia dice solo cosa può fare quell'oggetto. Ecco perché mi piace dire che qualcosa "implementa" piuttosto che "eredita da" un'interfaccia, che è ciò che direbbe la maggior parte delle persone .Net con cui ho lavorato (suppongo perché la sintassi è la stessa per ereditarietà e implementazione).
Ivan Pintar il

2

Le classi astratte possono presentare metodi protetti astratti (nelle lingue con cui sto lavorando), nelle interfacce i metodi sono generalmente sempre pubblici. Non so se questa differenza consenta utili sfruttamenti.

Modifica Ho pensato inizialmente che un metodo astratto privato non fosse di alcuna utilità, ma ora ho ricordato che potrebbe essere usato per garantire che quel metodo non venga mai chiamato. In questo modo è possibile impedire che venga chiamato un costruttore di copie di un oggetto.


1
I metodi virtuali protetti (abilitati per l'override) possono essere utili per le classi che fanno parte di un framework o qualcosa del genere. In questo modo assicurano che il codice personalizzato in una classe che eredita l'abstract fornisca tale funzionalità. Anche se questo può essere ottenuto anche ereditando un'interfaccia sulla classe base ma non implementando effettivamente i suoi metodi
Ivan Pintar,

Sì, stavo pensando a qualcosa del genere, ma non ho alcuna esperienza con esso, quindi non ho potuto giudicare. Grazie per l'input.
Thomas,

Solo una nota. In alcune lingue, i metodi virtuali privati ​​possono essere sovrascritti in classi derivate.
Johan Boulé,

2

Sì, sono diversi. Altrimenti i progettisti del linguaggio non avrebbero fornito entrambi. Conosco due lingue che separano classi e interfacce: Java e C #, clone mutante di Java. I progettisti hanno creato interfacce per evitare il supporto dell'ereditarietà di più classi. La maggior parte delle altre lingue supporta l'ereditarietà di più classi e di conseguenza non separa classi e interfacce.


2

Penso che la differenza principale sia che: in una classe astratta, anche se tutti i metodi sono tutti astratti, possono comunque fornire membri di dati (variabili di istanza) e del codice alle classi che lo implementano (sotto forma di metodi o costruttori privati), blocchi statici; facendo parte del lavoro per le sottoclassi e aiutandole nell'implementazione.

Un effetto collaterale positivo: il codice è in un posto, quindi in un posto per apportare correzioni. le sottoclassi possono semplicemente chiamare il metodo della superclasse e quindi fare qualcos'altro o niente se le azioni della superclasse sono sufficienti per il loro caso. La superclasse vuole che ogni sottoclasse prenda questa decisione, quindi ha contrassegnato tutta la sua implementazione come astratta (alcune potrebbero anche essere vuote)

Non pertinente alla domanda: ma avere interfacce significa che una classe può implementare due diversi contratti. Quindi questo è un vantaggio di un'interfaccia rispetto a una superclasse astratta


1
I metodi astratti non sono definiti senza alcuna implementazione e lasciano l'implementazione alle classi ereditarie?
Ivan Pintar,

sì, hai ragione, quindi immagino siano solo le variabili, i costruttori e i metodi statici e privati ​​se li conti
tgkprog

@Pinetree, in pratica il più delle volte vorrai almeno un po 'di codice "reale" nelle tue Classi astratte (almeno nella lingua che uso, che non ha un costrutto speciale per le Classi astratte).
Amy Blankenship,

@AmyBlankenship sì, la maggior parte delle volte le classi astratte hanno un codice "reale" (ecco a cosa servono). Ma mi riferivo a metodi astratti, nel contesto di una classe puramente astratta che funge da interfaccia in un linguaggio come C ++, che non ha interfacce.
Ivan Pintar il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.