venerdì 30 aprile 2010

Java: stop all'ereditarietà!

Una classe, così come le sue classi figlie, può essere estesa all'infinito. Nuove sottoclassi, allora, entreranno a far parte dell'albero delle classi ampliandone la profondità. Il blocco dell'ereditarietà può motivato dal giusto bilanciamento fra prestazioni ed efficienza: ogni chiamata a un metodo di una classe estesa genera un ulteriore carico (di ricerca del metodo nelle precedenti classi) per la JVM e quindi per il processore.
Una classe che non può essere estesa viene detta classe finale e l'identificatore che denota questa volontà è la parola chiave final (che precede l'identificatore class seguito poi dal nome della classe e segue eventualmente l'identificatore di visibilità, ad esempio public o private).
Quando una classe è descritta con l'identificatore final si estende tale proprietà a tutti i suoi metodi. Talvolta, anziché rendere finale un intera classe si decide di bloccare l'ereditarietà di uno o più metodi. In tal caso l'identificatore final precede il nome del metodo. La classe estesa erediterà, allora, il metodo finale (uno o più e gli altri metodi) ma non avrà modo di riscrivere lo stesso! Le chiamate ai metodi finali possono essere ottimizzate dalla JVM (che sa a che livello dell'ereditarietà andare a cercare il metodo quando viene invocato).
Attenzione, se i metodi di una classe final non possono essere ampliati è opportuno ricordare che l'accesso ai campi pubblici dell'istanza (di una classe final), se esistono, continuano ad essere accessibili! Qualcuno potrebbe rintracciarne i valori e scrivere con questi nuove funzioni! Tuttavia, se organizziamo bene le classi, incapsulando bene i dati, possiamo evitare anche quest'ultima eventualità. Infatti, se i campi dell'istanza sono privati i metodi dell'interfaccia pubblica della classe finale verranno ereditati come metodi finali e quindi non riscrivibili.

/* tutti i metodi sono automaticamente final */
import Elfo.*;
public final class Wizard extends Elfo {
   ...
}

/* solo il metodo attack() è final */
import Elfo.*;
public class Wizard extends Elfo {
   public final int attack() {
   ...
   }
   ...
}

Nessun commento:

Posta un commento