Quali sono le differenze tra classi astratte, interfacce e quando usarle

14

Recentemente ho iniziato a girare la testa intorno a OOP, e ora sono al punto in cui più leggo sulle differenze tra classi astratte e interfacce più divento confuso. Finora, nessuno dei due può essere istanziato. Le interfacce sono più o meno progetti strutturali che determinano lo scheletro e gli abstract sono diversi in quanto sono in grado di implementare parzialmente il codice.

Mi piacerebbe saperne di più su questi attraverso la mia situazione specifica. Ecco un link alla mia prima domanda se desideri un po 'più di informazioni di base: Che cos'è un buon modello di progettazione per la mia nuova classe?

Ecco due classi che ho creato:

class Ad {
    $title;
    $description
    $price;

    function get_data($website){  }

    function validate_price(){  }
 }


class calendar_event {
    $title;
    $description

    $start_date;

    function get_data($website){ //guts }

    function validate_dates(){ //guts }
 }

Quindi, come puoi vedere queste classi sono quasi identiche. Non mostrato qui, ma ci sono altre funzioni, like get_zip() , save_to_database() che sono comuni tra le mie classi. Ho anche aggiunto altre classi Cars e Animali che hanno tutti i metodi comuni e naturalmente le proprietà specifiche di quelle classi (chilometraggio, peso, per esempio).

Ora ho violato il principio DRY e sto gestendo e modificando lo stesso codice su più file. Intendo avere più classi come barche, cavalli o qualsiasi altra cosa.

Quindi è qui che utilizzerei un'interfaccia o una classe astratta? Da ciò che capisco delle classi astratte, utilizzerei una super classe come modello con tutti gli elementi comuni incorporati nella classe astratta e quindi aggiungerei solo gli elementi specificatamente necessari nelle classi future. Ad esempio:

abstract class content {
    $title;
    $description


    function get_data($website){  }

    function common_function2() { }
    function common_function3() { }
 }


class calendar_event extends content {

    $start_date;

    function validate_dates(){  }
 }

O dovrei usare un'interfaccia e, poiché sono così simili, creare una struttura che ciascuna delle sottoclassi sia obbligata a usare per ragioni di integrità, e lasciare che sia lo sviluppatore finale a capire che quella classe è responsabile per ciascuno dei dettagli anche delle funzioni comuni. il mio pensiero è che alcune funzioni "comuni" potrebbero aver bisogno di essere ottimizzate in futuro per le esigenze della loro classe specifica.

Nonostante tutto quanto sopra, se credi di fraintendere il cosa e il perché delle classi e delle interfacce astratte del tutto, lascia che una risposta valida smetta di pensare in questa direzione e suggerisca il modo corretto di andare avanti!

Grazie!

    
posta user66662 04.11.2012 - 00:38
fonte

6 risposte

24

In parole povere:

Interfacce sono per "possono / possono essere trattati come" tipo di relazioni.

Le classi astratte (così come concrete) sono per "è un tipo di relazione .

Guarda questi esempi:

class Bird extends Animal implements Flight;
class Plane extends Vehicle implements Flight, AccountableAsset;
class Mosquito extends Animal implements Flight;
class Horse extends Animal;
class RaceHorse extends Horse implements AccountableAsset;
class Pegasus extends Horse implements Flight;

Bird , Mosquito e Horse sono Animals . Sono correlati. Essi ereditano metodi comuni da Animal come eat(), metabolize() and reproduce() . Forse hanno la precedenza su questi metodi, aggiungendo qualcosa in più a loro, ma sfruttano il comportamento predefinito implementato in Animal come metabolizeGlucose().

Plane non è correlato a Bird , Mosquito o Horse .

Flight è implementato da classi dissimili e non correlate, come Bird e Plane .

AccountableAsset è anche implementato da classi dissimili, non correlate, come Plane e RaceHorse .

Horse non implementa Flight.

Come puoi vedere classi (astratto o concreto) ti aiuta a costruire gerarchie , consentendo di ereditare il codice dai livelli superiori ai livelli inferiori della gerarchia. In teoria, meno sei nella gerarchia, più il tuo comportamento è specializzato, ma non devi preoccuparti di molte cose che sono già state prese in considerazione.

Interfacce , d'altra parte, non creano gerarchie, ma possono aiutare omogeneizzare determinati comportamenti attraverso le gerarchie in modo da poterli astrarre dalla gerarchia in determinati contesti.

Ad esempio puoi avere un programma sommare il valore di un gruppo di AccountableAssets indipendentemente dal fatto che siano RaceHorses o Planes .

    
risposta data 04.11.2012 - 03:04
fonte
13

È possibile dedurre la risposta in modo logico dal momento che sembra essere consapevole delle differenze tra i due.

Interfacce definisce un contratto comune. Come un'interfaccia chiamata IAnimal, in cui tutti gli animali condividono funzioni come Eat (), Move (), Attack () ecc. Mentre tutti condividono le stesse funzioni, tutti o molti di essi hanno un modo diverso (implementazione) di raggiungere esso.

Le classi astratte definiscono un'implementazione comune e opzionalmente i contratti comuni. Ad esempio un semplice calcolatore può essere qualificato come una classe astratta che implementa tutti gli operatori logici e bit a bit di base e quindi viene esteso da ScientificCalculator, GraphicalCalculator e così via.

Se hai un'implementazione comune, allora con tutti i mezzi, incapsula la funzionalità in una classe astratta da cui estendersi. Ho quasi 0 esperienza PHP, ma non penso che tu possa creare interfacce con campi non costanti. Se i campi sono comuni tra le tue classi di istanze, sei costretto a utilizzare una classe Abstract, a meno che tu non ne definisca l'accesso tramite getter e setter.

Inoltre, sembra non esserci mancanza di risultati in Google.

    
risposta data 04.11.2012 - 02:09
fonte
3

La differenza è sottile ma chiara. L'interfaccia riguarda il comportamento polimorfico. La classe astratta riguarda il riutilizzo e il comportamento polimorfico.

Se vuoi porre l'accento sul riutilizzo e sul comportamento polimorfico, scegli una classe astratta. Ad esempio, i diversi tipi di dipendenti hanno disposizioni diverse, ma tutti ricevono alcuni elementi comuni. Quindi, la classe astratta è idonea a rappresentarla perché le comunanze possono essere espresse in una classe astratta base Employee e la differenza può essere implementata in classi derivate come Manager o Worker ecc.

Se vuoi porre l'accento sul solo comportamento polimorfico, scegli l'interfaccia. L'interfaccia riguarda più il contratto, ovvero un oggetto o una gerarchia che dice che è conforme a determinati comportamenti. Ad esempio, tutti i dipendenti dispongono di congedi per le ferie, ma i diversi tipi di dipendenti hanno diversi tipi di disposizioni. Quindi, ogni diverso tipo di dipendente richiede un calcolatore di congedo diverso. Qui l'interfaccia è una buona scelta perché tutti i tipi di dipendenti possono implementare un'interfaccia LeaveCalculator con un comportamento Calculate() diverso.

    
risposta data 04.11.2012 - 04:18
fonte
3

Per farla breve. Le classi astratte sono molto simili alle interfacce in quanto entrambe forniscono un modello di quali metodi dovrebbero essere inclusi nella classe ereditaria, ma ci sono grandi differenze: - Le interfacce definiscono solo nomi / tipi di metodi che devono esistere in una classe ereditaria, mentre le classi abs possono avere un codice di metodo completo e solo i dettagli potrebbero dover essere superati. - Le interfacce non possono avere modificatori di accesso. - Le interfacce non possono avere campi. - Le classi non possono avere ereditarietà multipla delle classi, mentre possono ereditare più interfacce. - Inoltre, le classi forniscono una struttura gerarchica in modo che solo le classi derivate da una classe specifica debbano seguire le linee guida della classe astratta: oggetto- > oggetto specifico- > oggetto molto specifico. Le interfacce d'altra parte possono essere ereditate da chiunque ovunque.

Secondo me le classi astratte sono più comuni in quanto possono fornire l'implementazione di default del codice subito, ma in progetti su larga scala in cui è necessario standardizzare determinate classi, le interfacce potrebbero rivelarsi utili.

Spero che aiuti, ma ci sono molte informazioni su questo online, Leo

    
risposta data 04.11.2012 - 01:09
fonte
3

Prima di tutto, dovresti capire che spesso fornisci sia un'interfaccia che una classe astratta. La ragione di questo, e la differenza principale tra i due, è che ti permettono di riutilizzare codice diverso, e quindi di risolvere diversi problemi.

Le interfacce ti consentono di riutilizzare il codice cliente con diverse implementazioni. A un cliente della classe get_data ($ website) non interessa il titolo $ o gli articoli $ description. Vuole solo istruire i tuoi contenuti per caricare i dati. Se si dispone di diversi tipi di contenuto, alcuni dei quali richiedono una descrizione $ e altri no, è possibile fornire una classe ContentInterface che specifica solo la firma delle classi figlio. Ora il cliente può avere un numero qualsiasi di contenuti diversi senza sapere esattamente come funzionano. Il principio di sostituzione di Liskov è una buona cosa da leggere su cui studiare questa idea. Mi piace anche scrivere Uncle Bob sull'argomento. Le interfacce sono molto importanti per il test delle unità e la creazione di interfacce è una buona abitudine da imparare.

Le classi astratte consentono di riutilizzare i dettagli di implementazione comuni su un insieme di classi che condividono un antenato comune. Nella tua domanda sembra che tu abbia una buona padronanza del motivo per cui potresti ereditare l'implementazione da una classe astratta. È ancora pericoloso dipendere dall'interno di una classe base: è molto facile violare l'incapsulamento e creare figli che dipendono da specifici dettagli di implementazione di una classe base. Il modello di metodo dei modelli fornisce un esempio comune e salutare di come utilizzare le classi di base senza violare l'incapsulamento.

Quindi, come spero di aver dimostrato, spesso fornirai interfacce per i client della tua gerarchia di classi, così puoi tranquillamente cambiare la tua implementazione senza influenzare il codice del client. Ciò consente al cliente di scrivere test unitari usando Mock Objects che ereditano la tua interfaccia. E fornirai anche classi astratte che consentono il riutilizzo della logica comune o l'applicazione della semantica per le classi figlie.

    
risposta data 04.11.2012 - 02:31
fonte
-3
  1. La principale differenza è che i metodi di un'interfaccia Java sono implicitamente astratti e non possono avere implementazioni. Una classe astratta Java può avere metodi di istanza che implementano un comportamento predefinito.
  2. Le variabili dichiarate in un'interfaccia Java sono per default definitive. Una classe astratta può contenere variabili non definitive.
  3. I membri di un'interfaccia Java sono pubblici per impostazione predefinita. Una classe astratta Java può avere i soliti sapori dei membri della classe come privati, protetti, ecc.
  4. L'interfaccia Java dovrebbe essere implementata usando la parola chiave "implements"; Una classe astratta Java dovrebbe essere estesa usando la parola chiave "extends".
  5. Un'interfaccia può estendere un'altra interfaccia Java solo una classe astratta può estendere un'altra classe Java e implementare più interfacce Java.
  6. Una classe Java può implementare più interfacce ma può estendere solo una classe astratta.
  7. L'interfaccia è assolutamente astratta e non può essere istanziata; Anche una classe astratta Java non può essere istanziata, ma può essere invocata se esiste un main ().
  8. In confronto con le classi astratte java, le interfacce java sono lente in quanto richiede un'ulteriore indiretta.
  9. Interfaccia e classe astratta in Java è che non è possibile creare un metodo non astratto nell'interfaccia, ogni metodo nell'interfaccia è di default astratto, ma è possibile creare un metodo non astratto in classe astratta.
  10. La classe astratta rispetto all'interfaccia in Java è che le interfacce sono più adatte per la dichiarazione di tipo e la classe astratta è più adatta per il riutilizzo del codice e la prospettiva dell'evoluzione.
risposta data 06.02.2013 - 15:48
fonte

Leggi altre domande sui tag