Questo Post tratta uno dei concetti fondamentali dell’Object Oriented che prende il nome di Encapsulation, ed è una di quelle “regole” da seguire se si vuole ambire ad una buona progettazione Object Oriented. L’Encapsulation è anche uno degli argomenti da conoscere se si vuole superare la Certicazione Java, per la precisione copre parte dell’ Objective 5.1 della section 5.
* Develop code that implements tight encapsulation, loose coupling, and high cohesion in classes, and describe the benefits.
Per capire bene di cosa si tratta è meglio partire da un esempio. Per fare questo definiamo una semplice classe come segue:
public class Car{
public int speed;
public int weight;
}
Come si può vedere la classe Car è caratterizzata da due attributi speed e weight entrambi public. Questo significa che chiunque può accedere agli attributi e modificarli a proprio piacimento. Per evidenziare questo fatto consideriamo il seguente codice:
public class MyTest{
public void main(String[] args){
Car car = new Car();
car.speed=-20;
car.weight=5;
}
}
Sulla Classe Car non abbiamo, quindi, nessun controllo sui suoi attributi e, quindi, chiunque ne fa uso puo’ modificare gli attributi della classe a suo piacimento, con tutto cio’ che ne consegue. L’Encapsulation, invece, ci permette di monitorare e controllare completamente i valori che possono essere assegnati agli attributi della classe, di fatto nascondendoli e impedendo, quindi, un accesso diretto che puo’ avvenire solo attraverso specifici metodi. Se tutti gli attributi della classe sono ecapsulati allora si parla di Tight Encapsulation. Modifichiamo la nostra classe in modo che rispetti l’Encapsulation il risultato sara’ quindi il seguente:
public class Car{
private int speed;
private int weight;
public void setSpeed(int value){
if(value>100){
this.speed=value;
}else{
this.speed=100;
}
}
public int getSpeed(){
return this.speed;
}
public void setWeight(int value){
// si può definire un controllo sul valore immesso per Weight
this.weight=value;
}
public int getWeight(){
return this.weight;
}
}
Definire una classe che rispetti la Tight Encapsulation e’ quindi molto semplice. E’ sufficiente definire tutti i campi della classe come private, e per ognuno di questi definire dei metodi getter e setter che permettano l’accesso allo specifico campo. La naming convention usata è quella dei JavaBeans cioè:
set<PropertyName>
get<PropetyName>
Da notare che gli attributi devono essere rigorosamente definiti privati e non protected. L’uso di protected implica esporre l’attributo alle classi derivate e a livello di package che ne avranno quindi il pieno controllo. Il modificatore di accesso protected va quindi usato solo quando e’ veramente indispensabile.
I benefici nell’uso della Tight Encapsulation sono notevoli, non solo nel caso in cui si decida di effettuare dei controlli di validazione sui campi della classe, ma soprattutto perchè si puo’ nascondere l’implementazione della classe rendendo il codice piu’ flessibile, manuntenibile e estensibile. Se gli attributi di una classe sono nascosti (hidden) allora è possibile cambiare l’implementazione senza dover modificare tutte le classi che ne fanno uso. Il codice di sopra può essere, ad esempio, modificato senza cambiare la classe MyTest che la usa, nella seguente maniera:
public class Car{
private String speed;
private String weight;
public void setSpeed(int value){
if(value>100){
this.speed=Integer.toString(value);
}else{
this.speed="100";
}
}
public int getSpeed(){
return Integer.parseInt(this.speed);
}
public void setWeight(int value){
this.weight=Integer.toString(value);
}
public int getWeight(){
return Integer.parseInt(this.weight);
}
}
Si può notare anche che la classe Car è stata modificata pesantemente(vedere gli statement evidenziati) senza che però vi siano degli impatti sulle altre classi che ne fanno uso. Questa caratteristica dell’Encapsulation prende il nome di Information Hiding. Se non si ha un’accesso diretto agli attributi e’ possibile modifcare il tipo(data type) dell’attributo stesso senza dover modificare i punti in cui viene usato indirettamente attraverso i metodi get e set, ma ovviamente non bisogna modificare la signature di questi metodi. Un altro vantaggio dell’encapsulation e’ anche quello di facilitare il disaccoppiamento con le altre classi, infatti quello che viene nascosto non puo’ essere accoppiato
E’ sempre consigliabile usare il più possibile l’encapsulation anche se non si prevede inizialmente di effettuare dei controlli di validazione degli attributi o di scrivere delle logiche particolari nei metodi getter e setter. Tutto ciò può essere fatto anche in seguito eliminando il problema di dover modificare il codice che usa la nostra classe.





1 comment so far ↓
The next step is trying to delete getters and setters so that you can encapsulate also the list of fields and not only their implementation. For instance, providing method accelerate() and brake() without giving (at least writing) access to speed.
Leave a Comment