Un esercizio interessante per introdurre le proprietà di composizione e aggregazione, cominciando quindi ad entrare nel vivo della OOP in cui più oggetti possono di fatto essere in relazione tra loro. Qui proponiamo una aggregazione in cui la carrozza è un elemento chiave per la costruzione di un treno. Analizziamo nel dettaglio le singole classi con i loro metodi proposti.

Indice dei contenuti
Classe Carrozza
Cominciamo dalla più piccolina delle due classi. Ha 3 attributi semplici ed intuitivi: un identificatore e due interi che equivalgono al numero di passeggeri di prima e seconda classe.
Tra i costruttori evidenziamo il costruttore vuoto, il costruttore che prende tutti e tre i parametri corrispondenti degli attributi e il costruttore di copia che appunto copia i dati di un’altra carrozza passata come parametro.
I metodi accessori, oltre ai set e get che diamo per scontati, sono pochi e semplici:
- totalePasseggeri(): restituisce il numero di passeggeri sommando la prima e seconda classe
- stampaInfo(): stampa le informazioni della singola carrozza, gli attributi e il totale dei passeggeri
- Il codice non è complesso e non presenta particolari elementi da approfondire. L’unica cosa che può spaventare il lettore è la formattazione della stampaInfo. Qui, per simulare una sorta di card, abbiamo utilizzato una funzione String.format() che in pratica crea una stringa di lunghezza fissa riempiendo con spazi bianchi a seconda del valore che c’è dentro immerso. Ad esempio, in ogni riga dai due punti : sulla sinistra al bordo destro ci sono 16 caratteri preimpostati e che vanno riempiti in caso col vuoto.
class Carrozza
{
private String ID;
private int nPasseggeriPrima;
private int nPasseggeriSeconda;
//COSTRUTTORI
public Carrozza(){}
public Carrozza(String id, int prima, int seconda)
{
this.ID = id;
this.nPasseggeriPrima = prima;
this.nPasseggeriSeconda = seconda;
}
public Carrozza(Carrozza c)
{
this.ID = c.getID();
this.nPasseggeriPrima = c.getnPasseggeriPrima();
this.nPasseggeriSeconda = c.getnPasseggeriSeconda();
}
//METODI DI ACCESSO
public String getID() {
return ID;
}
public void setID(String ID) {
this.ID = ID;
}
public int getnPasseggeriPrima() {
return nPasseggeriPrima;
}
public void setnPasseggeriPrima(int nPasseggeriPrima) {
this.nPasseggeriPrima = nPasseggeriPrima;
}
public int getnPasseggeriSeconda() {
return nPasseggeriSeconda;
}
public void setnPasseggeriSeconda(int nPasseggeriSeconda) {
this.nPasseggeriSeconda = nPasseggeriSeconda;
}
//METODI ACCESSORI
public int totalePasseggeri()
{
return this.nPasseggeriPrima + this.nPasseggeriSeconda;
}
public void stampaInfo()
{
System.out.println("|-----------------------------------|");
System.out.println("| CARROZZA |");
System.out.println("|-----------------------------------|");
System.out.println("| ID : " + String.format("%-16s", this.ID) + "|");
System.out.println("| # Prima Classe : " + String.format("%-16s", this.nPasseggeriPrima) + "|");
System.out.println("| # Seconda Classe: " + String.format("%-16s", this.nPasseggeriSeconda) + "|");
System.out.println("| # Totale : " + String.format("%-16s", this.totalePasseggeri()) + "|");
System.out.println("|-----------------------------------|");
}
}
Classe Treno
Veniamo alla classe Treno, decisamente più complessa ed articolata.
Gli attributi sono piuttosto intuitivi e semplici da esaminare. Il lettore potrebbe solo spaventarsi della classe LocalTime che in realtà è del tutto analoga alla LocalDate, elementi cardine della programmazione OOP per gestire in modo semplice le date nel classico formato gg/mm/aaaa e le ore hh:mm:ss. Occhio che LocalTime verrà segnalato come “rosso” ma passando il cursore del mouse sul tipo (senza cliccare), si dovrebbe aprire una tendine con il suggerimento di importare la relativa libreria.
Veniamo però all’aggregazione: ci sono 3 attributi privati di tipo Carrozza, la classe che abbiamo preparato precedentemente. All’alunno alle prime armi suona strano e spesso vengono a chiedere: “ma carrozza che tipo è, una stringa? No, c’è scritto: è di tipo Carrozza” Ma in realtà scrivere un attributo LocalTime o String è già una aggregazione solo di una classe/tipo che non scriviamo noi ma che ci viene fornito dalla JDK.
I costruttori. Ce n’è uno vuoto, uno che prende le informazioni base tranne l’ora di arrivo che probabilmente non vogliamo inserire quando costruiamo il treno ma quando idealmente arriva. C’è poi il costruttore che prende tutte le informazioni del costruttore appena dichiarato, più le Carrozze. Qui una interessante proprietà dei costruttori: se uso la dicitura this(parametri) posso richiamare uno dei costruttori già dichiarati evitando di ricopiare la valorizzazione della variabili.
public Treno(String _codice, String _cp, String _ca, LocalTime _l)
{
this.codice = _codice;
this.cittaPartenza = _cp;
this.cittaArrivo = _ca;
this.oraPartenza = _l;
}
public Treno(String _codice, String _cp, String _ca, LocalTime _l, Carrozza c1, Carrozza c2, Carrozza c3)
{
this(_codice, _cp, _ca, _l); //richiama il costruttore con meno parametri
this.carrozza1 = c1;
this.carrozza2 = c2;
this.carrozza3 = c3;
}
equivale a semplificare la seguente:
public Treno(String _codice, String _cp, String _ca, LocalTime _l)
{
this.codice = _codice;
this.cittaPartenza = _cp;
this.cittaArrivo = _ca;
this.oraPartenza = _l;
}
public Treno(String _codice, String _cp, String _ca, LocalTime _l, Carrozza c1, Carrozza c2, Carrozza c3)
{
this.codice = _codice;
this.cittaPartenza = _cp;
this.cittaArrivo = _ca;
this.oraPartenza = _l;
this.carrozza1 = c1;
this.carrozza2 = c2;
this.carrozza3 = c3;
}
Il this(parametro) permette di realizzare in modo semplice e veloce costruttori con svariate combinazioni di parametri risparmiando tempo di digitazione nel caso la classe presenti numerosi attributi. Questo non toglie che l’alunno spaventato non possa evitarne l’uso e copiare di costruttore in costruttore tutti i parametri con le relative assegnazioni agli attributi.
I metodi accessori cosa comprendono?
- tempoDiPercorrenza() è il più interessante. Qui restituisce un valore LocalTime che altro non è che la combinazioni di ore e minuti e secondi che intercorre tra l’orario di arrivo e quello di partenza. Potremmo lasciarlo in secondi o moltiplicarlo per ottenere minuti e ore ma utilizzare la funzionalità della classe LocalTime ovvero LocalTime.ofSecondOfDay(tempo); è semplice ed intuitivo: basta fornire i secondi che in automatico tira fuori ore e minuto corrispondenti. I secondi li abbiamo ottenuti facendo la differenza degli orari convertiti in secondi sempre con le spettacolari funzioni messe a disposizione .toSecondOfDay();
- totalePasseggeri() è molto semplice: restituisce un intero col numero di passeggeri di tutte le carrozze, che siano di prima che di seconda classe
- mediaPasseggeriPerCarrozza(): sulle orme del metodo precedente, restituisce un double con la media diviso 3 della precedente somma
- stampaInfo() stampa a video le informazioni del treno, sia quelle degli attributi sia quelle calcolate con i metodi accessori. Anche qui abbiamo usato la funzione String.format per avere una grafica più piacevole ma l’alunno può procedere ad una stampa più semplice e secca
- svuotaTreno() imposta a zero i passeggeri di tutte le carrozze
- svuotaCarrozza() prende un numero intero e va ad azzerare i passeggeri di quella carrozza. Andrebbe aggiunto un controllo che il numero inserito sia 1 o 2 o 3 ma vedremo più avanti questo genere di controllo
import java.time.LocalTime;
class Treno
{
private String codice;
private String cittaPartenza;
private String cittaArrivo;
private LocalTime oraPartenza;
private LocalTime oraArrivo;
private Carrozza carrozza1;
private Carrozza carrozza2;
private Carrozza carrozza3;
//COSTRUTTORI
public Treno(){}
public Treno(String _codice, String _cp, String _ca, LocalTime _l)
{
this.codice = _codice;
this.cittaPartenza = _cp;
this.cittaArrivo = _ca;
this.oraPartenza = _l;
}
public Treno(String _codice, String _cp, String _ca, LocalTime _l, Carrozza c1, Carrozza c2, Carrozza c3)
{
this(_codice, _cp, _ca, _l); //richiama il costruttore con meno parametri
this.carrozza1 = c1;
this.carrozza2 = c2;
this.carrozza3 = c3;
}
public Treno(Treno _t)
{
this.codice = _t.getCodice();
this.cittaPartenza = _t.getCittaPartenza();
this.cittaArrivo = _t.getCittaArrivo();
this.oraPartenza = _t.getOraPartenza();
this.oraArrivo = _t.getOraArrivo();
this.carrozza1 = _t.getCarrozza1();
this.carrozza2 = _t.getCarrozza2();
this.carrozza3 = _t.getCarrozza3();
}
//METODI DI ACCESSO
public String getCodice() {
return codice;
}
public void setCodice(String codice) {
this.codice = codice;
}
public String getCittaPartenza() {
return cittaPartenza;
}
public void setCittaPartenza(String cittaPartenza) {
this.cittaPartenza = cittaPartenza;
}
public String getCittaArrivo() {
return cittaArrivo;
}
public void setCittaArrivo(String cittaArrivo) {
this.cittaArrivo = cittaArrivo;
}
public LocalTime getOraPartenza() {
return oraPartenza;
}
public void setOraPartenza(LocalTime oraPartenza) {
this.oraPartenza = oraPartenza;
}
public LocalTime getOraArrivo() {
return oraArrivo;
}
public void setOraArrivo(LocalTime oraArrivo) {
this.oraArrivo = oraArrivo;
}
public Carrozza getCarrozza1() {
return carrozza1;
}
public void setCarrozza1(Carrozza carrozza1) {
this.carrozza1 = carrozza1;
}
public Carrozza getCarrozza2() {
return carrozza2;
}
public void setCarrozza2(Carrozza carrozza2) {
this.carrozza2 = carrozza2;
}
public Carrozza getCarrozza3() {
return carrozza3;
}
public void setCarrozza3(Carrozza carrozza3) {
this.carrozza3 = carrozza3;
}
//METODI ACCESSORI
public LocalTime tempoDiPercorrenza()
{
int tempo = -1;
if (this.oraArrivo != null)
{
tempo = this.oraArrivo.toSecondOfDay() - this.oraPartenza.toSecondOfDay();
//tempo = tempo *60; //minuti
}
return LocalTime.ofSecondOfDay(tempo);
}
public int totalePasseggeri()
{
int totale = this.carrozza1.totalePasseggeri() +
this.carrozza2.totalePasseggeri() +
this.carrozza3.totalePasseggeri();
return totale;
}
public double mediaPasseggeriPerCarrozza()
{
int totale = this.carrozza1.totalePasseggeri() +
this.carrozza2.totalePasseggeri() +
this.carrozza3.totalePasseggeri();
return totale / 3;
}
public void stampaInfo()
{
System.out.println("|-----------------------------------|");
System.out.println("| TRENO |");
System.out.println("|-----------------------------------|");
System.out.println("| Codice : " + String.format("%-19s", this.codice) + "|");
System.out.println("| Parte Da : " + String.format("%-19s", this.cittaPartenza) + "|");
System.out.println("| Arriva A : " + String.format("%-19s", this.cittaArrivo) + "|");
System.out.println("| Ora Partenza : " + String.format("%-19s", this.oraPartenza) + "|");
System.out.println("| Ora Arrivo : " + String.format("%-19s", this.oraArrivo) + "|");
System.out.println("| Tempo (hh:mm): " + String.format("%-19s", this.tempoDiPercorrenza()) + "|");
System.out.println("| Passeggeri : " + String.format("%-19s", this.totalePasseggeri()) + "|");
System.out.println("| Media : " + String.format("%-19s", this.mediaPasseggeriPerCarrozza()) + "|");
System.out.println("|-----------------------------------|");
}
public void svuotaTreno()
{
this.carrozza1.setnPasseggeriPrima(0);
this.carrozza1.setnPasseggeriSeconda(0);
this.carrozza2.setnPasseggeriPrima(0);
this.carrozza2.setnPasseggeriSeconda(0);
this.carrozza3.setnPasseggeriPrima(0);
this.carrozza3.setnPasseggeriSeconda(0);
}
}
Classe Main
E’ il momento di testare con delle istanze le nostre classi e metodi vari. La classe Main in questi primi esempi di programmazione Java OOP diventa un ottimo test. Sperimentiamo perciò i vari costruttori, valorizziamo e stampiamo gli attributi con i metodi set/get e verifichiamo con le varie stampe la bontà dei dati attesi.
import java.time.LocalTime;
class Main
{
public static void main(String[] args)
{
Carrozza c1 = new Carrozza();
Carrozza c2 = new Carrozza();
Carrozza c3 = new Carrozza();
c3.setID("T1000");
c3.setnPasseggeriPrima(20);
c3.stampaInfo();
Treno teramomilano = new Treno("T001",
"Teramo",
"Milano",
LocalTime.of(12,30,00),
c1,
c2,
c3
);
System.out.println();
Treno palermoroma = new Treno("T002",
"Palermo",
"Roma",
LocalTime.of(14,00,00),
new Carrozza("A",12,11),
new Carrozza("B",2,7),
new Carrozza("C",5,9)
);
palermoroma.setOraArrivo(LocalTime.of(18,0,0));
palermoroma.stampaInfo();
System.out.println();
palermoroma.svuotaTreno();
palermoroma.stampaInfo();
}
}
Il file draw
Alleghiamo il file .draw per poterlo modifica e personalizzare sul sito www.draw.io
Ultima modifica 30 Ottobre 2022