L'implementazione iniziale contiene:
public class Autobus {
…
private Autorimessa autorimessa;
…
}
|
public class Autorimessa {
…
private HashSet<Autobus> autobus;
…
}
|
L'autobus contiene un collegamento alla eventuale autorimessa in cui si trova. L'autorimessa contiene un collegamento all'insieme degli autobus che vi si trovano. Queste due componenti possono sempre venire aggiornate diversamente. Alcuni esempi:
Autobus a; Autorimessa r; a.setRimessa(r);
Autobus a, b; Autorimessa r; a.setRimessa(r); r.aggiungiAutobus(b);
Autobus a, b; Autorimessa r; a.setRimessa(r); r.aggiungiAutobus(a); r.aggiungiAutobus(b);
Autobus a, b; Autorimessa r, s; a.setRimessa(null); r.aggiungiAutobus(a); s.aggiungiAutobus(b);
Sono errori che possono avvenire:
La soluzione è che i due cambiamenti devono sempre avvenire in coppia, con oggetti scambiati fra loro, ma in Java non esiste un costrutto primitivo per forzare due istruzioni a venire sempre eseguite in coppia e mai singolarmente.
a.setOfficina(o); o.aggiungiAutobus(a);
In aggiunta, il controllo non si può fare con il solo codice sorgente, perchè i valori delle due variabili possono cambiare a seconda dell'input dell'utente, di dati ricevuti da rete, ecc.
Autobus a; Officina o, r; if (...) r = o; else r = … a.setOfficina(o); r.aggiungiAutobus(a); // corretto solo se r=o
Il vincolo dei cambiamenti coerenti si può imporre con un complesso uso dei permessi di accesso public e private. Le due istruzioni devono trovarsi all'interno di un metodo che ha un accesso esclusivo alle due componenti. In altre parole, non esiste modo di cambiare le due componenti se non all'interno di quel metodo, e in quel metodo le due compomenti vengono cambiate insieme e in modo coerente.