Le classi e le interfacce astratte sono molto popolari in tutti i linguaggi di programmazione orientati agli oggetti. E in quasi tutte le interviste Java trovi almeno una domanda su questo argomento. Le interfacce vengono menzionate più spesso a causa della loro popolarità tra i progettisti di software, ma di tanto in tanto sorgono anche domande sulle classi astratte. A questi ultimi vengono spesso poste domande per la posizione di sviluppatori junior, diciamo, con non più di due anni di esperienza nello sviluppo Java, mentre domande sulle interfacce si incontrano più spesso durante i colloqui con coloro la cui esperienza ha già superato i quattro anni. Generalmente vengono poste insieme ad altre domande sui modelli di progettazione Java, come i modelli Decorator o Factory.
In questo articolo esamineremo le domande più comuni su classi astratte e interfacce poste a vari livelli delle interviste Java. La maggior parte di essi non dovrebbe essere difficile nemmeno per un programmatore Java alle prime armi. Si tratta per lo più di domande di pura conoscenza, ma alcune di esse, come
le differenze tra classi astratte e interfacce in Java, o quando
scegliere una classe astratta anziché un'interfaccia , possono essere piuttosto complicate. Ti offriamo una dozzina di domande interessanti sull'argomento.
Se ti è mai stata posta una domanda in un'intervista o hai dovuto porre qualche domanda utile su classi e interfacce astratte, ma non è presente in questo elenco, condividila nei commenti. |
1. Una classe astratta può avere costruttori in Java?
Sì, in una classe astratta in Java puoi dichiarare e definire costruttori. Poiché è impossibile creare istanze di classi astratte, un tale costruttore può essere chiamato solo quando si forma una catena di costruttori, cioè quando si crea un'istanza di una specifica classe di implementazione. Ma immagina che l’intervistatore poi ponga la domanda: qual è lo scopo di un costruttore se non puoi comunque creare un’istanza di una classe astratta? Il punto è che può ancora essere utilizzato per impostare i valori iniziali di variabili comuni dichiarate in una classe astratta e utilizzate da varie implementazioni. Anche se non dichiari alcun costruttore, il compilatore aggiungerà un costruttore predefinito senza argomenti alla classe astratta. Senza di essa, la tua sottoclasse non verrà compilata perché la prima istruzione in qualsiasi costruttore è una chiamata implicita
super()
al costruttore della superclasse predefinito in Java.
2. Le classi astratte in Java possono implementare interfacce? Devono implementare tutti i metodi?
Sì, le classi astratte possono implementare interfacce utilizzando
implements
. Poiché sono astratti, non è necessario che implementino tutti i metodi. Avere una classe base astratta e un'interfaccia per dichiarare il tipo è una pratica consigliata. Un esempio è un'interfaccia
java.util.List
e la corrispondente classe astratta
java.util.AbstractList
. Poiché
AbstractList
implementa tutti i metodi comuni, implementazioni specifiche (come
LinkedList
e
ArrayList
) non devono necessariamente implementare tutti i metodi, come accadrebbe se implementassero
List
direttamente l'interfaccia. Questa soluzione combina il vantaggio di utilizzare un'interfaccia per dichiarare un tipo con la flessibilità di una classe astratta per implementare tutto il comportamento comune in un unico posto. Nel libro di Joshua Bloch
"Java. Effective Programming” contiene un ottimo capitolo sul tema dell'utilizzo delle interfacce e delle classi astratte in Java, per una migliore comprensione è opportuno studiarlo.
3. Una lezione astratta può essere definitiva?
No non può. La parola chiave
final
significa che la classe è al vertice della gerarchia e non può avere discendenti. E una classe astratta senza eredi è un cavallo sferico nel vuoto, poiché è impossibile crearne un'istanza
abstract class
. Pertanto, se una classe è sia
abstract
e
final
, allora non ha discendenti e non può essere istanziata. Il compilatore Java genererà un errore se crei una classe
abstract
e
final
.
4. Una classe astratta in Java può avere metodi statici?
Sì, le classi astratte possono dichiarare e definire metodi statici. È solo necessario seguire i principi generali della creazione di metodi statici in Java, poiché non sono desiderabili nella progettazione orientata agli oggetti, poiché non è possibile sovrascrivere i metodi statici in Java. I metodi statici in una classe astratta sono molto rari, ma se ci sono buone ragioni per farlo, nulla ti impedisce di usarli.
5. È possibile istanziare una classe astratta?
No, non puoi farlo. L'essenza di una classe astratta è che non è completa e deve essere completata nelle classi discendenti. Cioè, questa classe non è pronta per l'uso. Ad esempio, potrebbe mancare l'implementazione di alcuni metodi. Poiché una classe non è pronta per l'uso, il suo oggetto non può essere creato. Ma puoi creare istanze di eredi di una classe astratta. Il compilatore Java genererà un errore se un programma tenta di istanziare una classe astratta.
6. È necessario che una classe astratta disponga di metodi astratti?
No, una classe astratta non può avere metodi astratti. Puoi creare una classe astratta in Java semplicemente utilizzando una parola chiave
abstract
nella sua dichiarazione. Il compilatore applicherà eventuali restrizioni strutturali, ad esempio non consentire la creazione di istanze di questa classe. A proposito, la questione se debbano esserci metodi astratti in una classe o interfaccia astratta è controversa. Mi sembra che una classe astratta dovrebbe avere metodi astratti, poiché questa è la prima cosa a cui pensa un programmatore quando vede una classe astratta. Ciò si adatta bene al principio di ridurre al minimo le sorprese.
7. Quali sono le differenze tra una classe astratta e un'interfaccia in Java?
Questa è la domanda più importante e una delle più classiche dell'intervista Java. Non riesco a contare quante volte ho visto questa domanda nelle interviste Java a tutti i livelli. Ciò che rende interessante questa domanda è soprattutto la possibilità per il richiedente di fornire un esempio. Rispondere a domande sulle basi della programmazione orientata agli oggetti, come astrazione, incapsulamento, polimorfismo ed ereditarietà, è facile, ma quando si tratta di sfumature così sottili, i candidati spesso si confondono e dicono la prima cosa che viene in mente.
La risposta a questa domanda meriterebbe un articolo a parte (soprattutto dopo le modifiche apportate a Java 8), tuttavia in breve:
- Un'interfaccia descrive solo il comportamento (metodi) di un oggetto, ma non ha stati (campi) (eccetto
public static final
), mentre una classe astratta può averli.
- Una classe astratta viene ereditata (si estende) e un'interfaccia viene implementata (implementa). Possiamo ereditare solo una classe, ma implementare quante interfacce vogliamo. Un'interfaccia può estendere (estendere) un'altra interfaccia/interfacce.
- Le classi astratte vengono utilizzate quando esiste una relazione "is-a", ovvero la sottoclasse estende la classe astratta di base e le interfacce possono essere implementate da classi diverse che non sono affatto correlate tra loro.
8. Quando ha senso preferire una classe astratta ad un'interfaccia e viceversa?
Questa è una continuazione delle domande precedenti su classi e interfacce astratte. Se sai quali sono le loro differenze sintattiche, rispondere a questa domanda non ti causerà problemi, poiché sono il fattore determinante nel prendere una decisione. Poiché è quasi impossibile aggiungere un nuovo metodo a un'interfaccia pubblicata, è meglio utilizzare una classe astratta in caso di potenziale necessità di ulteriore sviluppo. Sviluppare classi astratte in Java è più semplice che sviluppare interfacce. Allo stesso modo, se un'interfaccia ha troppi metodi e implementarli tutti diventa un vero grattacapo, è meglio creare una classe astratta per l'implementazione predefinita. Questo modello viene seguito nel pacchetto delle raccolte Java, la classe astratta
AbstractList
fornisce l'implementazione predefinita per
List
.
Utilizza classi astratte se:
- Desideri condividere il codice tra diverse classi strettamente correlate.
- Ci si aspetterebbe che le classi che estendono la classe astratta abbiano molti metodi o campi in comune o richiedano modificatori di accesso diversi da
public
(ad esempio protected
e private
).
- Vuoi dichiarare non statici o
не-final
campi. Ciò consente di definire metodi che possono accedere e modificare lo stato dell'oggetto a cui appartengono.
Utilizza le interfacce se:
- Ti aspetti che classi non correlate implementino la tua interfaccia. Ad esempio, le interfacce
Comparable
e Cloneable
sono implementate da molte classi non correlate.
- Vuoi definire il comportamento di un particolare tipo di dati, ma non ti interessa chi lo implementa.
- Si desidera utilizzare l'ereditarietà di più tipi.
9. Cos'è un metodo astratto in Java?
Un metodo astratto è un metodo senza corpo. Dichiari semplicemente un metodo senza definirlo, utilizzando una parola chiave
abstract
nella dichiarazione del metodo. Tutti i metodi dichiarati all'interno di un'interfaccia nel linguaggio Java sono astratti per impostazione predefinita. Ecco un esempio di un metodo astratto in Java:
public void abstract printVersion();
Ora, per implementare questo metodo, è necessario estendere la classe astratta e sovrascrivere questo metodo.
10. Una classe astratta in Java può contenere un metodo main
?
Sì, una classe astratta in Java può contenere un metodo
main
, perché è semplicemente un altro metodo statico e una classe astratta può essere eseguita utilizzando il metodo
main
, purché non ne venga istanziata. Questo è tutto quello che volevo dirti. E ricorda: le classi e le interfacce astratte sono decisioni di progettazione chiave nel processo di analisi e progettazione orientato agli oggetti e, ovviamente, dovrebbero essere utilizzate con la dovuta cautela se si desidera creare un sistema flessibile.
GO TO FULL VERSION