Quando incapsuli i dati, ti stai limitando a essere in grado di eseguire solo un numero limitato di operazioni su di esso. Ma spesso c'è un numero illimitato di cose che vuoi fare con i dati.
Supponiamo di scrivere un semplice gioco di ruolo. Scriviamo una classe Weapon
ed esaminiamo cosa succede se nascondiamo tutti i suoi dati.
public class Weapon {
private int damage;
private int accuracy;
public Weapon(int damage, int accuracy) {
this.damage = damage;
this.accuracy = accuracy;
}
}
Naturalmente, vogliamo essere in grado di colpire le persone con l'arma. Quindi abbiamo bisogno di una funzione che calcoli il danno che faremo al nemico. Ma tutte le variabili dell'arma sono private, quindi dovremo trasformare quella funzione in un metodo.
public int hitEnemy(Enemy theEnemy) {
return theEnemy.getDefense() - this.damage;
}
Avremo anche bisogno di un modo per determinare se siamo riusciti nel nostro attacco. Di nuovo, diventerà un metodo.
public boolean tryToHit(Enemy theEnemy) {
return random() > (theEnemy.getEvasion() - this.accuracy);
}
In seguito scopriremo che vogliamo confrontare due armi per vedere quale ha più danni. Un altro metodo.
public Order compareDamage(Weapon other) {
if (this.damage > other.damage) {
return Order.GREATER;
} else if (this.damage < other.damage) {
return Order.LESS;
} else {
return Order.EQUAL;
}
}
Alcuni giorni dopo decidiamo che il prezzo di un'arma dovrebbe essere determinato in base al suo danno e alla sua accuratezza ...
public int getPrice() {
return 10 * this.damage + 0.5 * this.accuracy;
}
La settimana seguente vogliamo dare le valutazioni delle armi da C a A in base alle loro statistiche ...
public Rating getRating() {
if (accuracy/10 + damage > 10) {
return Rating.A;
} else if (accuracy/10 + damage > 5) {
return Rating.B;
} else {
return Rating.C;
}
Come puoi vedere, ogni volta che dobbiamo fare qualcosa di nuovo con l'arma, dobbiamo lanciarlo nella classe dell'arma per ottenere le sue variabili. È sbagliato: viola il Principio Aperto / Chiuso , in cui si afferma che il codice deve essere aperto all'estensione e chiuso alla modifica . Se avessimo trasformato Weapon
in un semplice vecchio oggetto dati - un semplice record con nient'altro che dati pubblici - saremmo in grado di aggiungere funzioni per utilizzare le armi in modi nuovi senza dover modificare la classe Weapon
.
Quando progetti un'astrazione X, devi distinguere tra cose X fa e cose che posso fare con X . Le nostre armi non fanno nulla, quindi non ci sono dettagli di implementazione da nascondere. Nascondere tutti i loro dati dietro variabili private è utile tanto quanto un elenco che non ti consente di accedere ai suoi elementi. Il nostro gioco avrà sicuramente bisogno di incapsulamento e astrazione, ma dovrebbe essere implementato a un livello superiore, nella logica di gioco corretta.