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

8

Diciamo che abbiamo una classe astratta e 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, oggettivamente e nell'implementazione del linguaggio di programmazione sottostante tra una Classe astratta con solo membri astratti e un'interfaccia equivalente?

    
posta yfklon 19.04.2013 - 14:06
fonte

6 risposte

22

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

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

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

Ma sono tutti ancora animali e hanno alcune proprietà comuni, ad esempio se sono 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 puoi avere più interfacce su un oggetto, anche quando una lingua non supporta l'ereditarietà multipla.

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

    
risposta data 19.04.2013 - 14:38
fonte
19

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

    
risposta data 19.04.2013 - 14:10
fonte
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 suppongo che l'ereditarietà multipla possa causare problemi quando ci sono metodi con lo stesso nome nelle classi base.

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

Un'interfaccia funge da contratto per 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), esiste una relazione di "è", quindi Car è una Vehicle e Dog è una Animal . Con un'interfaccia, è ciò che importa l'oggetto. Quindi sia Car che Dog possono Move() e il consumatore lo sa perché implementano Movable , ma un'automobile non è sicuramente un Dog , o un Animal . E l'implementazione della mossa sarà diversa (ruote vs gambe) ma il codice che consuma non deve e non dovrebbe interessare. Le interfacce riguardano esclusivamente il codice che consuma, piuttosto che l'implementazione.

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

    
risposta data 19.04.2013 - 15:21
fonte
2

Le classi astratte possono presentare metodi protetti astratti (nelle lingue con cui lavoro), in genere i metodi di interfaccia sono sempre pubblici. Se questa differenza consente utili exploit che non conosco.

Modifica Per prima cosa ho pensato che un metodo astratto privato non servisse, ma ora ho ricordato che potrebbe essere usato per garantire che quel metodo non venga mai chiamato. In questo modo puoi impedire che venga chiamato un costruttore di copia di un oggetto.

    
risposta data 19.04.2013 - 14:23
fonte
2

Sì, sono diversi. Altrimenti i progettisti di linguaggi non avrebbero fornito entrambi. Conosco due linguaggi 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 degli altri linguaggi supporta l'ereditarietà di più classi e di conseguenza non separano classi e interfacce.

    
risposta data 19.04.2013 - 16:15
fonte
2

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

Un effetto collaterale positivo: il codice è in un posto, quindi un posto dove apportare correzioni. le sotto classi possono semplicemente chiamare il metodo super-classe e poi fare qualcos'altro o nulla se le azioni super class sono sufficienti per il loro caso. La super classe vuole che ogni sottoclasse prendesse questa decisione, quindi ha contrassegnato tutta la sua implementazione come astratta (alcuni potrebbero anche essere vuoti)

Non pertinente alla domanda: ma avendo un'interfaccia significa che una classe può implementare due contratti diversi. Quindi questo è un vantaggio di un'interfaccia su una super classe astratta

    
risposta data 19.04.2013 - 14:46
fonte