Il problema
Vogliamo gestire una certa quantità di autoveicoli dei quali ci interessano alcuni dati: la targa, il modello e quanti km riesce a fare con un litro di carburante, fornendo poi la lunghezza di un percorso vorremmo sapere quanto si spende con un determinato autoveicolo (supponendo che il carburante costi 1,5€ al litro).
Il nostro programma dovrà consentire all'utente di inserire diversi autoveicoli (al massimo 100) e in base alla targa e alla distanza calcolare la spesa del percorso.
Possibile soluzione
Dato che gli autoveicoli potrebbero essere molti useremo un vettore, visto che però le informazioni da registrare sono almeno tre (targa, modello e km/l) saremo costretti ad usare tre vettori: uno di stringhe per la targa, un altro di stringhe per il modello ed uno di double per i consumi. Ovviamente tutte le informazioni di un veicolo saranno registrate allo stesso indice in tutti e 3 i vettori.
Quella mostrata qui sotto è una possibile soluzione.
File: Programma.java
public class Programma extends Application{
String targa[];
String modello[];
double kmAlLitro[];
int autoRegistrate = 0;
TextField inTarga = new TextField();
TextField inModello = new TextField();
TextField inLitri = new TextField();
TextField calcTarga = new TextField();
TextField calcKm = new TextField();
Label risposta = new Label();
@Override
public void start(Stage primaryStage) throws Exception {
Button aggiungi = new Button("aggiungi auto");
Button calcolaSpesa = new Button("calcola spesa");
GridPane gp = new GridPane();
gp.add(new Label("targa:"),0,0);
gp.add(inTarga,1,0);
gp.add(new Label("modello:"),0,1);
gp.add(inModello,1,1);
gp.add(new Label("consumo:"),0,2);
gp.add(inLitri,1,2);
gp.add(aggiungi,1,3);
gp.add(new Label("targa:"),0,4);
gp.add(calcTarga,1,4);
gp.add(new Label("km/l:"),0,5);
gp.add(calcKm,1,5);
gp.add(calcolaSpesa,1,6);
gp.add(new Label("spesa:"),0,7);
gp.add(risposta,1,7);
Scene scena = new Scene(gp);
primaryStage.setScene(scena);
primaryStage.setTitle("automobili");
primaryStage.show();
aggiungi.setOnAction(e->aggiungiAuto());
calcolaSpesa.setOnAction(e->azioneSpesa());
// ci prendiamo una licenza: non ci saranno mai più di 100 automobili
targa = new String[100];
modello = new String[100];
kmAlLitro = new double[100];
}
public static void main(String args[]){
launch(args);
}
private void aggiungiAuto(){
String t = inTarga.getText();
String m = inModello.getText();
double km = Double.parseDouble(inLitri.getText());
targa[autoRegistrate] = t;
modello[autoRegistrate] = m;
kmAlLitro[autoRegistrate] = km;
autoRegistrate++;
risposta.setText(t+" registrata");
}
private void azioneSpesa(){
String t = calcTarga.getText();
double kilometri = Double.parseDouble(calcKm.getText());
int trovato = -1;
double spesa;
for(int i=0;i<autoRegistrate;i++){
if(targa[i].equals(t)) {
trovato=i;
}
}
if(trovato!=-1) {
spesa = kilometri/kmAlLitro[trovato]*1.5;
risposta.setText("l'automobile "+modello[trovato]+" spende "+spesa );
}else{
risposta.setText("non trovo "+t);
}
}
}
Questa soluzione funziona... e non è poco! Esiste però una diversa corrente di sviluppo del software che dice che è possibile seguire un altro approccio: visto che abbiamo parlato di autoveicoli dovremmo creare una loro rappresentazione!
Programmazione ad oggetti
Quello che ci proponiamo di fare è di spostare l'attenzione dal
"come fare le cose" (programmazione procedurale) al "modellare le entità della realtà" (programmazione ad oggetti).
La domanda a cui dobbiamo rispondere è:
"quali sono gli elementi fondamentali che compongono la realtà di cui si deve occupare il programma?"
È immediato che in questo esempio l'elemento da gestire è l'autoveicolo,
a questo punto segue la domanda: "cosa è un Autoveicolo?".
E con questo intendiamo sia "cosa caratterizza una autoveicolo" che "quali azioni possiamo fare con un autoveicolo".
Visto quanto abbiamo detto finora per noi un Autoveicolo è un un oggetto che:
- ha una targa (caratteristica)
- ha un modello (caratteristica)
- ha un certo consumo, misurato in km al litro (caratteristica)
- può calcolare quanto andremo a spendere dato un numero di km (azione)
Java ci permette di modellare la realtà in questo modo usando le classi. In effetti le abbiamo già create ogni volta che abbiamo scritto un programma ma fino a questo momento i programmi erano composti da una sola di esse e le abbiamo scritte senza prestare particolare attenzione a cosa stavamo rappresentando (solitamente una interfaccia grafica con delle funzionalità), quello che succede di solito quando si realizzano programmi più grandi è che si ha a che fare con più classi che usate insieme ci permettono di realizzare le funzionalità desiderate modellando la realtà che ci interessa.
Questo approccio porta alcuni vantaggi che diventano sempre più evidenti all'aumentare della dimensione del programma che si sta trattando, due tra i più evidenti sono:
- possiamo concentrare in un unico punto tutta la rappresentazione di una entità (l'autoveicolo dell'esempio), questo ci consentirà in futuro di poter cambiare il nostro modello intervenendo in un punto unico del programma
- quando più sviluppatori lavorano sullo stesso progetto possono occuparsi di entità diversi riducendo la possibilità di interferire l'uno con l'altro.
La struttura che Java ci mette a disposizione per modellare queste entità è la classe:
Una classe è un costrutto usato come modello per creare oggetti. Il modello comprende attributi e metodi e fornisce i valori iniziali per lo stato. In Java definendo una classe si definisce un nuovo tipo di dato.Una classe in Java viene definita in un file che ha il suo stesso nome utilizzando la parola chiave
class
seguita dal nome dell'entità e da un blocco di codice racchiuso tra parentesi graffe:
al loro interno è possibile trovare dichiarazione di proprietà o metodi
che riguardano l'entità.
Le proprietà sono usuali dichiarazioni di variabili fatte al livello di classe e i metodi sono delle funzioni che possono far riferimento alle proprietà dell'oggetto.
class Nome {
// proprietà
// metodi
}
Una proprietà (o attributo) è una variabile dichiarata all'interno di una classe
e concorre a rappresentarne lo stato.
...e quindi lo stato di un oggetto è rappresentato dal valore di tutte le sue proprietà. Nel nostro esempio lo stato di un Autoveicolo sono i valori della sua targa, del modello e del consumo.
Un metodo è un blocco di istruzioni identificato da un nome e dalla sequenza dei tipi dei parametri. Il nome e la sequenza dei tipi di parametri si chiama firma. Viene usato per raggiungere uno specifico obiettivo, può avere zero o più parametri e ritornare o meno un risultato.Mentre per distinguere una proprietà dall'altra si usa solo il nome, per distinguere due metodi non basta indicarne il nome perché con lo stesso nome possono esserci più metodi. Allora per chiarire a quale ci si riferisce, in modo tale da disambiguare l'identificazione e rendere l'invocazione del metodo univoca si passa a controllare i parametri. Di questi si controlla la sequenza dei tipi di argomenti e verrà invocato quello che ha l'esatta corrispondenza.
Chiaramente Java non permette di creare due metodi con la stessa firma nella stessa classe.
Ad esempio avere due metodi
public int faiMessaggio(String nome, int anni)
e public int faiMessaggio(String nome, int eta)
è
errore perché corrisponde il nome del metodo, entrambi hanno come primo parametro una stringa (non importa il nome della
variabile) ed entrambi hanno il tipo successivo intero quindi ci sarebbe ambiguità.
Invece avere
public int faiMessaggio(String nome, String anni)
e public int faiMessaggio(String nome, int anni)
è
corretto perché l'ultimo argomento in un caso è una stringa e nell'altro caso è un intero.
Nell'esempio dell'autoveicolo un metodo ci consente data una distanza (parametro) di calcolare quanto spenderemo per il percorso (risultato). In pratica un metodo è una funzione definita in una classe che oltre ai parametri può utilizzare anche i valori presenti nello stato, per calcolare la spesa servirà anche di utilizzare il consumo di un determinato autoveicolo (cioè il valore della sua proprietà "consumo").
Quale delle seguenti fa parte dello stato di Autoveicolo?
spesa no, è una azione che può compiere, un metodo targa giusto, è una delle sue proprietà Autoveicolo no, questo è il nome della classe modello giusto, è una delle sue proprietàCostruttore
Un particolare metodo è quello che viene usato quando costruiamo una nuovo oggetto:
il costruttore. Si riconosce perché ha lo stesso nome della classe e
nessun tipo ritornato (non c'è scritto void
,
è proprio assente). Per ogni classe è possibile definire molteplici costruttori con parametri diversi,
posso per esempio pensare ad un costruttore di Autoveicolo che voglia il solo numero di targa e
uno diverso che voglia sia numero di targa che il modello.
Se non si definisce nessun costruttore nella classe java
ne definisce uno predefinito che non accetta nessun parametro.
Quale è un possibile costruttore per la classe Tavolo
?
A questo punto possiamo scrivere l'intera classe Autoveicolo
:
public class Autoveicolo {
String targa;
String modello;
double kmAlLitro;
public Autoveicolo(String t, String m, double l){
targa = t;
modello = m;
kmAlLitro = l;
}
public double costoPercorso(double numeroKilometri) {
return numeroKilometri/kmAlLitro*1.5;
}
}
Istanze
Una classe ci permette di definire come si comporta una certa entità... abbiamo ad esempio
definito quali caratteristiche ha un Autoveicolo qualsiasi ma come
posso fare per creare qualcosa che rappresenti la mia particolare automobile che è una
"Stelvio" targata "CF876RT" che percorre 14km con un litro di carburante?
Posso farlo creando una particolare istanza della classe Autoveicolo
.
new
.
In pratica new
riserva dello spazio in memoria per registrare le informazioni
riguardanti una singola istanza di una classe (un oggetto) e quello che ritorna è un riferimento
alla zona di memoria appena riservata. Per questo motivo se io creo due oggetti che hanno
gli stessi valori su ogni proprietà (immaginiamo due Autoveicoli con stessa targa, stesso modello e stesso consumo)
e poi li confronto usando ==
questo mi restituirà falso
perché vengono confrontati i due riferimenti (che sono numeri che indicano
l'indirizzo di memoria in cui si trova l'oggetto) che sono diversi
(questo è il motivo per cui gli oggetti String non si confrontano con ==
ma utilizzando
il metodo equals()
).
Data la nostra classe di esempio potremmo creare tre sue diverse istanze:
automobileMario
, automobileLucia
e
automobileLuigi
che avranno lo stesso tipo ma ciascuna avrà un proprio stato
e quindi una sua targa, un suo modello e un suo consumo.
Autoveicolo automobileMario = new Autoveicolo("az897rr", "Panda", 18.3);
Autoveicolo automobileLucia = new Autoveicolo("pp915er", "Corsa", 16.3);
Autoveicolo automobileLuigi = new Autoveicolo("ba523et", "Discovery", 6.3);
Possiamo a questo punto rivedere una riga di codice che abbiamo scritto molte volte:
Button pulsante = new Button()
. Con questa istruzione abbiamo creato
una nuova istanza (un oggetto) della classe Button
usando l'operatore new
e chiamando dopo di lui uno dei suoi costruttori.
Ma si può scrivere anche la dichiarazione: Button pulsante = new Button("Premi qui")
e anche questa volta abbiamo invocato un metodo che si chiama come la classe.
L'unica differenza è che il primo metodo invocato non aveva argomenti, questo qui ha un argomento di tipo stringa.
Quale è lo scopo dei 2 costruttori della classe Button?
Avere modi diversi per creare dei Button (sono tre), chi ha scritto la classe
ha deciso in quali modi sia possibile instanziarla, possiamo ipotizzare che nel primo caso si vuole un pulsante senza testo
e nel secondo caso si vuole un pulsante con del testo al suo interno.
Ogni istanza di una classe avrà le stesse proprietà ma con valori diversi, per accedere a queste proprietà
(o anche ai metodi) si usa la notazione punto: se voglio accedere ad una proprietà
di un oggetto scrivo il nome di una istanza seguita dal punto e dal nome della proprietà (o del metodo) che
si vuole usare.
Se ho creato una istanza automobileMario
di Autoveicolo
posso impostare la sua targa scrivendo automobileMario.targa="xd987tt"
.
Quale dei seguenti non è un operatore?
+ no, più è un operatore che esegue la somma degli operandi new no, new crea nuovi oggetti * no, esegue il prodotto tra due numeri _ giusto, la linea bassa non è un operatoreCosa conterrà la variabile falcon
dopo la seguente istruzione?
Autoveicolo falcon = new Autoveicolo("xf675ee", "astronave", 4)
?
Facendo riferimento alla classe Autoveicolo definito qui sopra
Autoveicolo autoAnna = new Autoveicolo("uj7643pl", "Ferrari 488", 11);
Autoveicolo autoLuigi = new Autoveicolo("tg530oo", "Fiat panda", 21);
autoLuigi.kmAlLitro = 29;
Quanto valgono rispettivamente autoAnna.kmAlLitro e autoLuigi.kmAlLitro ?
11 e 29 giusto, la prorietà kmAlLitro di autoAnna è stata impostata con il costruttore, quella di autoLuigi è stata impostata nell'ultima riga 29 e 29 nella terza riga abbiamo modificato soltanto il valore delle proprietà kmAlLitro di autoLuigi 11 e 21 il valore della proprietà kmAlLitro di autoLuigi è stato modificatome stesso
Capita a volte che all'interno di un metodo in una classe serva di far riferimento
all'oggetto stesso, in questo caso è possibile usare la parola chiave this
che indica appunto l'oggetto corrente. Perché mai dovrebbe servire? In generale
per evitare di far confusione tra i nomi delle proprietà e i nomi dei parametri dei metodi.
Proviamo a vedere come è possibile riscrivere il costruttore del nostro Autoveicolo (in effetti normalmente vengono scritti così):
File: Autoveicolo.java aggiornato
public class Autoveicolo {
String targa;
String modello;
double kmAlLitro;
public Autoveicolo(String t, String m, double l){
targa = t;
modello = m;
kmAlLitro = l;
}public Autoveicolo(String targa, String modello, double kmAlLitro){
this.targa = targa;
this.modello = modello;
this.kmAlLitro = kmAlLitro;
}
}
L'istruzione this.targa = targa
serve a copiare il valore della variabile targa
passata al costruttore nella proprietà targa
di questo oggetto (quello che stiamo creando).
Dopo un possibile senso di confusione iniziale il costruttore che usa this è più chiaro da leggere rispetto a quello che non usa this.
Una per tutti: le proprietà statiche
Riprendiamo l'esempio dell'automobile, poniamo che il nostro programma tratti soltanto di automobili a benzina e che vogliamo aggiungere una proprietà prezzoBenzina: il prezzo della benzina ovviamente non varia da automobile a automobile. A cosa serve allora una proprietà che si deve impostare sempre allo stesso valore per ogni oggetto creato?
Non ha significato dire che il il costo della benzina per automobileMario
è 1,78€/litro
che lascerebbe intendere che per altre automobili il prezzo è diverso.
Sarebbe senz'altro più comodo dire: tutti gli oggetti creati di tipo Autoveicolo condividono il fatto che
la benzina ha un certo costo.
Quello che vogliamo dire è che tutti gli oggetti della classe Autoveicolo pagano la
benzina 1,78€/litro.
Quindi, considereremo concettualmente sbagliato avere la proprietà private double prezzoBenzina;
.
Per rappresentare
in Java questa situazione, andiamo a scrivere la proprietà aggiungendo la parola chiave static:
static double prezzoBenzina;
.
La variabile per rappresentare una proprietà creata in questo modo è unica e condivisa da tutti gli oggetti della classe,
esiste anche se non viene creata alcuna istanza.
Poniamo ora di voler calcolare quanti litri di benzina possiamo acquistare con 10€:
per calcolarlo abbiamo bisogno soltanto della variabile prezzoBenzina e questo valore
non varia da istanza a istanza della classe Autoveicolo
.
Per enfatizzare il fatto che tali metodi possono essere invocati indipendentemente dall'oggetto su cui si sta lavorando, o anche semplicemente se esiste o meno un oggetto della classe Autoveicolo anche qui si inserisce la parola static:
static double prezzoBenzina;
static double litriDieciEuro() {
return 10/prezzoBenzina;
}
Quando nel programma si vuole utilizzare questo metodo, si dovrà utilizzare la forma
Autoveicolo.litriDieciEuro()
cioè si fa riferimento
direttamente alla classe piuttosto che ad una sua istanza.
In definitiva esiste un modo per far sì che tutti gli oggetti della stessa classe condividano un valore:
usare il modificatore static
. Le variabili e i metodi così definiti possono essere usati senza
creare una istanza della classe cioè senza creare un oggetto con new
. Esempi di proprietà e
metodi statici già disponibili in Java sono Math.PI o Math.random() o anche Integer.parseInt().
Attenzione ad una cosa: i metodi static
possono vedere soltanto le variabili static
perché non facendo parte di una istanza di una classe non possono vedere le varaibili di istanza
(quelle non static
) le quali vengono create, appunto, col new
.
Organizzare gli oggetti
Abbiamo già detto che un programma è spesso formato da molte classi, un paio di meccanismi ci consentono di tenerle organizzate:
- uno è il sistema di pacchetti che ci permette di raggruppare classi che hanno scopi simili in strutture analoghe alle cartelle
- un altro è quello che consente di specificare cosa gli altri oggetti possono vedere dell'oggetto che stiamo definendo
I modificatori public
o private
che vengono scritti
prima del tipo nella dichiarazione delle variabili o dei metodi servono per definire
se una proprietà (o un metodo) possono essere visti al di fuori della classe che si sta
definendo, in realtà questi modificatori sono quattro: public
, protected
,
private
e uno senza nome, sono però facilmente comprensibili:
modificatore di visibilità | la proprità/metodo si può usare nella | |||
---|---|---|---|---|
classe | pacchetto | sottoclasse | tutti | |
public | si | si | si | si |
protected | si | si | si | no |
| si | si | no | no |
private | si | no | no | no |
Attenzione alla terza riga: se non scrivo nulla faccio una scelta ben precisa e diversa dalle altre!
Una buona strategia generale è quella di evitare che gli altri oggetti possano modificare lo stato (cioè una delle proprietà) degli oggetti direttamente ma di creare appositi metodi che chiedano all'oggetto di modificare il suo stato. Doppio vantaggio:
- se decido di rappresentare diversamente lo stato interno di un oggetto ma lascio intatti i metodi pubblici non devo cambiare gli altri oggetti
- se chi usa l'oggetto decide di impostare un valore errato si possono fare i controlli
Quello che si fa normalmente è definire una qualsiasi proprietà come private
e poi definire due metodi che ci consentono di impostarne o leggerne il valore.
Questi metodi hanno per convenzione il nome che inizia con get o set
a seconda che si voglia leggere o impostare il valore della proprietà, vediamo
ad esempio questo meccanismo per la proprietà targa:
private String targa;
// per leggere il valore della proprietà targa
public String getTarga(){
return targa;
}
// per impostare il valore della proprietà targa
public void setTarga(String targa){
this.targa=targa;
}
Eclipse può aiutarci nella generazione dei getters and setters:
click col destro sulla classe nel Package Explorer o sullo sfondo nella finestra del sorgente
quindi click sulla voce Generate getters and setters...
Nella finestra che si aprirà si scelgono i setters e getters per le singole proprietà o per tutte.
Automobile: confronto tra versione procedurale e a oggetti
Proviamo a confrontare due programmi che svoilgono lo stesso lavoro: il primo con un approccio ad oggetti, il secondo procedurale.
La nuova versione ad oggetti
usa un oggetto: Autoveicolo
con le proprietà
marca
, modello
e kmAlLitro
mentre i metodi sono: un costruttore
un altro per calcolare il costo di un percorso.
La vecchia versione procedurale del programma non usa gli oggetti
File: Autoveicolo.java
public class Autoveicolo {
String targa;
String modello;
double kmAlLitro;
public Autoveicolo(String targa, String modello, double kmAlLitro){
this.targa = targa;
this.modello = modello;
this.kmAlLitro = kmAlLitro;
}
public double costoPercorso(double numeroKilometri) {
return numeroKilometri/kmAlLitro*1.5;
}
}
File: Programma.java
public class Programma extends Application{
String targa[];
String modello[];
double kmAlLitro[];
Autoveicolo automobili[];
int autoRegistrate = 0;
TextField inTarga = new TextField();
TextField inModello = new TextField();
TextField inLitri = new TextField();
TextField calcTarga = new TextField();
TextField calcKm = new TextField();
Label risposta = new Label();
@Override
public void start(Stage primaryStage) throws Exception {
Button aggiungi = new Button("aggiungi auto");
Button calcolaSpesa = new Button("calcola spesa");
GridPane gp = new GridPane();
gp.add(new Label("targa:"),0,0);
gp.add(inTarga,1,0);
gp.add(new Label("modello:"),0,1);
gp.add(inModello,1,1);
gp.add(new Label("consumo:"),0,2);
gp.add(inLitri,1,2);
gp.add(aggiungi,1,3);
gp.add(new Label("targa:"),0,4);
gp.add(calcTarga,1,4);
gp.add(new Label("km/l:"),0,5);
gp.add(calcKm,1,5);
gp.add(calcolaSpesa,1,6);
gp.add(new Label("spesa:"),0,7);
gp.add(risposta,1,7);
Scene scena = new Scene(gp);
primaryStage.setScene(scena);
primaryStage.setTitle("automobili");
primaryStage.show();
aggiungi.setOnAction(e->aggiungiAuto());
calcolaSpesa.setOnAction(e->azioneSpesa());
// ci prendiamo una licenza: non ci saranno mai più di 100 automobili
targa = new String[100];
modello = new String[100];
kmAlLitro = new double[100];
automobili = new Autoveicolo[100];
}
public static void main(String args[]){
launch(args);
}
private void aggiungiAuto(){
String t = inTarga.getText();
String m = inModello.getText();
double km = Double.parseDouble(inLitri.getText());
targa[autoRegistrate] = t;
modello[autoRegistrate] = m;
kmAlLitro[autoRegistrate] = km;automobili[autoRegistrate] = new Autoveicolo(t, m, km);
autoRegistrate++;
risposta.setText(t+" registrata");
}
private void azioneSpesa(){
String t = calcTarga.getText();
double kilometri = Double.parseDouble(calcKm.getText());
int trovato = -1;Autoveicolo trovata = null;
double spesa;
for(int i=0;i<autoRegistrate;i++){
if(targa[i].equals(t)) {
trovato=i;
}if(automobili[i].targa.equals(t)) {
trovata = automobili[i];
}
}
if(trovato!=-1) {
spesa = kilometri/kmAlLitro[trovato]*1.5;
risposta.setText("l'automobile "+modello[trovato]+" spende "+spesa );
}
if(trovata!=null) {
spesa = trovata.costoPercorso(kilometri);
risposta.setText("l'automobile "+trovata.modello+" spende "+spesa );
}else{
risposta.setText("non trovo "+t);
}
}
}
Test!
Primo.java
Data la classe:
public class Primo {
int x;
boolean y;
public Primo(int k, boolean p) {
x = k;
y = p;
}
public int leggiVal() {
int p;
if(y) {
p = x;
} else {
p = -x;
}
return p;
}
public String descrivi(){
return "n:"+x;
}
private boolean check(){
return x<100;
}
}
Cosa è Primo
?
Quanti parametri ha il costruttore della classe precedente?
0c'è un costruttore dichiarato con più di zero parametri quindi in questo caso quello di default non viene inserito da java) 1 2 un int e un boolean non c'è il costruttoreConsidera il seguente frammento di programma inserito in un'altra classe:
Primo o;
o = new Primo(3,false);
int q = o.leggiVal();
Quanto vale q?
Considera il seguente frammento di programma inserito in un'altra classe:
Primo o;
o = new Primo(3,false);
boolean q = o.check();
Quanto vale q?
Considera il seguente frammento di programma inserito in un'altra classe:
Primo o;
o = new Primo(3,false);
String m = o.descrivi();
Quanto vale m?
Esempio.java
Data la classe:
public class Esempio {
public static n;
public int w;
String c;
public Esempio(String u){
c = u;
}
public String descrivi(){
return n + c;
}
}
Considera il seguente frammento di programma inserito in un'altra classe:
Esempio t1 = new Esempio("1");
Esempio t2 = new Esempio("2");
t1.n = 5;
t2.n = 7;
Quanto vale t1.n?
n
static t2.n=7 la sovrascrive
7
Considera il seguente frammento di programma inserito in un'altra classe:
Esempio t1 = new Esempio("1");
Esempio t2 = new Esempio("2");
t1.w = 5;
t2.w = 7;
Quanto vale t1.w?
w
una variabile di istanza (non static) t2.n=7 non la sovrascrive
7 essendo w
una variabile di istanza (non static) t2.n=7 non la sovrascrive
Considera il seguente frammento di programma inserito in un'altra classe:
Esempio t1 = new Esempio("1");
Esempio t2 = new Esempio("2");
Esempio.n = 10;
Quanto vale t1.n?