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


15

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

Vorrei saperne di più su questi attraverso la mia situazione specifica. Ecco un link alla mia prima domanda se desideri ulteriori informazioni di base: qual è un buon modello di design 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 è riportato, ma ci sono altre funzioni, like get_zip(), save_to_database()che sono comuni a tutti i miei corsi. Ho anche aggiunto altre classi di auto e animali domestici che hanno tutti i metodi comuni e, naturalmente, proprietà specifiche per quelle classi (chilometraggio, peso, ad esempio).

Ora ho violato il principio DRY e sto gestendo e modificando lo stesso codice su più file. Ho intenzione di avere più classi come barche, cavalli o altro.

Quindi è qui che utilizzerei un'interfaccia o una classe astratta? Da quello che ho capito delle classi astratte, userei una super classe come modello con tutti gli elementi comuni incorporati nella classe astratta, quindi aggiungerei solo gli elementi specificamente necessari nelle classi future. Per 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 userei un'interfaccia e, poiché sono così simili, creerei una struttura che ciascuna delle sottoclassi è costretta a usare per motivi di integrità e la lascerei allo sviluppatore finale che completa quella classe per essere responsabile di ciascuna delle dettagli anche delle funzioni comuni. il mio pensiero è che in futuro potrebbe essere necessario modificare alcune funzioni "comuni" per le esigenze della loro classe specifica.

Nonostante tutto quanto sopra, se credi che io fraintenda il cosa e il perché di classi e interfacce astratte del tutto, lascia che una risposta valida sia smettere di pensare in questa direzione e suggerisci il modo corretto di andare avanti!

Grazie!


Ci sono molti buoni esempi online. Penso che questo sia uno di questi. javapapers.com/core-java/abstract-and-interface-core-java-2/…
Siva

Risposte:


26

In parole povere:

Le interfacce sono per "può fare / può essere trattato come" tipo di relazioni.

Classi astratte (oltre che 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, MosquitoE Horse sono Animals . Sono correlati. Essi ereditano metodi comuni da animali simili eat(), metabolize() and reproduce(). Forse hanno la precedenza su questi metodi, aggiungendo un piccolo extra ad essi, ma sfruttano il comportamento predefinito implementato in Animal likemetabolizeGlucose().

Planenon è correlato a Bird, Mosquitoo Horse.

Flightè implementato da classi diverse, non correlate, come Birde Plane.

AccountableAssetè anche implementato da classi diverse, non correlate, come Planee RaceHorse.

Horse non implementa Flight.

Come puoi vedere, le classi (astratte o concrete) ti aiutano a costruire una gerarchia , permettendoti di ereditare il codice dai livelli superiori ai livelli inferiori della gerarchia. In teoria, più basso sei nella gerarchia, più specializzato è il tuo comportamento, ma non devi preoccuparti di molte cose di cui hai già preso cura.

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

Ad esempio, puoi avere un programma che somma il valore di un gruppo AccountableAssetsindipendentemente dal loro essere RaceHorseso Planes.


Sorprendente. Interface fornisce una certa sezione di funzionalità che impone can do/can be treated asdove le classi astratte fungono da base!
Abhiroj Panwar,

13

Potresti dedurre la risposta logicamente poiché sembri essere consapevole delle differenze tra i due.

Le interfacce definiscono 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 la maggior parte di essi ha un modo diverso (implementazione) di raggiungere esso.

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

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

Inoltre, non sembrano mancare risultati in Google.


3

Per farla breve. Le classi astratte sono molto simili alle interfacce in quanto entrambe forniscono un modello di quali metodi dovrebbero essere all'interno della classe ereditaria, ma ci sono grandi differenze: - Le interfacce definiscono solo nomi / tipi di metodi che devono esistere in una classe ereditaria, mentre abs- le classi possono avere un codice di metodo predefinito completo e potrebbe essere necessario sovrascrivere solo i dettagli. - Le interfacce non possono avere modificatori di accesso. - Le interfacce non possono avere campi. - Le classi non possono avere eredità multiple di 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 invece possono essere ereditate da chiunque ovunque.

A mio avviso, le classi astratte sono più comuni in quanto possono fornire immediatamente l'implementazione predefinita del codice, ma nei progetti su larga scala in cui è necessario standardizzare determinate classi, le interfacce potrebbero tornare utili.

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


2
Classes cannot have multiple inheritance- Vero per linguaggi come Java e C #, non vero per C ++.
Robert Harvey,

3

Prima di tutto, dovresti capire che spesso fornirai un'interfaccia e una classe astratta. Il motivo di ciò, e la differenza fondamentale tra i due, è che ti consentono di riutilizzare codice diverso e quindi di risolvere problemi diversi.

Le interfacce consentono di riutilizzare il codice client con diverse implementazioni. Un cliente della tua classe get_data ($ website) non si preoccupa degli articoli $ title o $ description. Vuole solo istruire i tuoi contenuti a caricare i dati. Se hai diversi tipi di contenuto, alcuni dei quali richiedono una descrizione $ e altri no, potresti fornire una classe ContentInterface che specifica solo la firma delle classi secondarie. Ora il cliente può avere un numero qualsiasi di contenuti diversi senza che tutti sappiano esattamente come funzionano. Il principio di sostituzione di Liskov è una buona cosa da leggere per studiare questa idea. Mi piace anche la scrittura di zio Bob sull'argomento. Le interfacce sono molto importanti per i test unitari e la creazione di interfacce è una buona abitudine da imparare.

Le classi astratte ti consentono di riutilizzare i dettagli di implementazione comuni in un insieme di classi che condividono un antenato comune. Nella tua domanda sembra che tu abbia una buona idea del perché erediterai l'implementazione da una classe astratta. È ancora pericoloso dipendere dagli interni 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 Metodo modello fornisce un esempio comune e salutare di come utilizzare le classi di base senza violare l'incapsulamento.

Quindi, come spero di aver dimostrato, fornirai spesso interfacce per i client della tua gerarchia di classi, in modo da poter cambiare in modo sicuro l'implementazione senza influire sul codice client. Ciò consente al client di scrivere test unit utilizzando Mock Objects che ereditano l'interfaccia. E fornirai anche classi astratte che consentono il riutilizzo della logica comune o impongono la semantica per le classi figlio.


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 la classe astratta. Ad esempio, i diversi tipi di dipendenti hanno disposizioni diverse ma tutti ricevono alcuni comuni. Quindi, la classe astratta è adatta a rappresentarla perché i punti comuni possono essere espressi in una classe astratta di base Employeee la differenza può essere implementata in classi derivate come Managero Workerecc.

Se si desidera porre l'accento solo sul comportamento polimorfico, scegliere l'interfaccia. L'interfaccia riguarda più il contratto, ovvero un oggetto o una gerarchia che afferma che è conforme a determinati comportamenti. Ad esempio, tutti i dipendenti hanno un congedo, ma diversi tipi di dipendenti hanno diversi tipi di disposizioni. Quindi, ogni diverso tipo di dipendente richiede un diverso congedo. Qui l'interfaccia è una buona scelta perché tutti i tipi di dipendenti possono implementare LeaveCalculatorun'interfaccia con un Calculate()comportamento diverso.


-3
  1. La differenza principale è 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 di default final. Una classe astratta può contenere variabili non finali.
  3. I membri di un'interfaccia Java sono pubblici per impostazione predefinita. Una classe astratta Java può avere i soliti gusti dei membri della classe come privati, protetti, ecc.
  4. L'interfaccia Java dovrebbe essere implementata usando la parola chiave "implementa"; 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 di Java, le interfacce Java sono lente in quanto richiedono un'ulteriore indiretta.
  9. L'interfaccia e la 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 contro l'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 di evoluzione.
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.