classe=tipo degli oggetti (es. String, Point, Rectangle)
Da non confondere con la parola class che va messa all'inizio del programma!
tutti gli oggetti di uno stesso tipo hanno in comune:
Definire una nuova classe=specificare quali componenti o metodi ha una classe
In questa lezione: definire le componenti di una classe
Primo: a cosa serve la classe?
Esempio: dati di uno studente:
Sarebbe comodo avere oggetti cosí:
public static void main() { Studente s, q; s.nome="Tizio Semproni"; s.data="12/3/1932"; s.media="18"; ... }
Se si compila questo programma, dà errore (il tipo Studente non esiste).
Utile: quando si deve definire un nuovo tipo di dati, scrivere prima un programma in cui si usa.
Serve a capire come deve essere fatto l'oggetto.
Dal programma di esempio, si capisce che il nuovo tipo dovrebbe essere fatto cosí:
A parole, il nuovo tipo viene specificato cosí:
Crea nuovo tipo di oggetti Studente con: | componente String, di nome .nome | componente String, di nome .data | componente int, di nome .media
Questa definizione a parole si può ottenere guardando il programma di esempio.
Infatti, dal programma si vede che il tipo si chiama Studente, mentre ogni variabile di questo tipo ha queste tre componenti.
Questo è quello che voglio dire al calcolatore:
Crea nuovo tipo di oggetti Studente con: | componente String, di nome .nome | componente String, di nome .data | componente int, di nome .media
Non è codice Java.
Nella sintassi del linguaggio, diventa:
class Studente { String nome; String data; int media; }
Fare attenzione:
La definizione della classe va in un file,
il programma va in una altro.
Sono due file separati
File Studente.java:
|
File DBUniv.java:
|
Attenzione!
Non posso fare class Studente in tutti e due i file.
Cosa devo fare?
Le istruzioni da eseguire stanno nel programma.
Quindi, eseguo il programma.
La classe dice solo come sono fatti i dati di un certo tipo.
Una dichiarazione int x ha significato diverso se sta nel programma o nella classe:
Nel programma: definisco una variabile; nella classe: dico come saranno fatti internamente gli oggetti.
Se fa int x, cosa succede?
Finora: descrizione a parole --> definizione di classe
Ora, il contrario: classe --> descrizione a parole
class Studente { String nome; String data; int media; }
significa the Studente è un nuovo tipo di dato, e che ogni variabile di questo tipo ha una componente String di nome .nome, una componente String di nome .data e una int di nome .media
Dare la descrizione a parole di questo nuovo tipo:
class Abcd { int x; int y; }
Facciamo il processo meccanico inverso:
class Abcd { int x; int y; }
Con le regole di prima, significa:
Crea nuovo tipo di dato Abcd con: | componente int di nome x | componente int di nome y
È semplicemente l'inversione della traduzione di prima.
Crea nuovo tipo di dato Abcd con: | componente int di nome x | componente int di nome y
Sulla base di questa descrizione, scrivere un programma di esempio.
Ossia, voglio un programma che usa questa classe
Dato che Abcd è il nome della classe, si possono definire variabili di quel tipo, e creare:
class Prova { public static void main(String args[]) { Abcd a, b; a=new Abcd(); b=new Abcd(); ...
Attenzione! Questo è il programma (l'altro era il file di definizione del tipo).
Dato che Abcd ha componenti x e y, sono definite le variabili intere a.x, a.y, b.x e b.y
class Prova { public static void main(String args[]) { Abcd a, b; a=new Abcd(); b=new Abcd(); a.x=12; a.y=3; b.x=4; b.y=-1; System.out.println(a.x); } }
Quando faccio int x nella classe, non è una dichiarazione di variabile.
Se non creo nessun oggetto Abcd, allora non viene creata nessuna variabile .x, se creo cento oggetti creo cento variabili .x, ecc.
Ho due variabili in questo programma, ma potevo
usarne uno, tre, cento, ecc.
Non c'entra con il fatto che questi oggetti
hanno due componenti.
Abbiamo visto solo come definire classi senza metodi.
Anche se sono definite la componenti x e y, non è definito il metodo distance, ecc.
Vedremo poi come si fanno a definire i metodi per le nuove classi.
Ogni oggetto contiene i dati di un film: titolo, regista, anno di uscita e durata del film.
Seguire la solita procedura:
So quali sono i dati:
crea un nuovo tipo di dati Film con: | componente String di nome titolo | componente String di nome regista | componente int di nome anno | componente int di nome durata
Un qualsiasi programma che usa variabili di tipo Film va bene, per ora:
class ProvaFilm { public static void main(String args[]) { Film f; f=new Film(); f.titolo="Ombre rosse"; f.regista="Ford"; f.anno=1958; f.durata=120; int x; x=f.anno-2; System.out.println(f.titolo); } }
Nota: l'istruzione System.out.println(f) non stampa tutte le componenti di f
Si tratta di tradurre la descrizione a parole:
class Film { String regista; String titolo; int anno; int durata; }
Specifiche del tipo:
Da questa definizione è possibile definire il tipo in modo univoco!
In base quanto detto sopra:
crea un nuovo tipo Corso con: | componente String di nome .titolo | componente String di nome .docente | componente int di nome .anno | componente int di nome .ore
Questo serve per due motivi:
Un esempio di possibile programma:
class Ing { public static void main(String args[]) { Corso fondam; fondam=new Corso(); fondam.titolo="Fondamenti di Informatica"; fondam.docente="Paolo Liberatore"; fondam.anno=2002; fondam.ore=100; // aggiornare al nuovo anno fondam.anno=fondam.anno+1; System.out.println(fondam.titolo); System.out.println(fondam.docente); System.out.println(fondam.ore); } }
Il nome del file in cui questo va messo è Ing.java
Il nome del file deve coincidere con quello che è scritto dopo class
Qualsiasi altro programma che definiva una o più variabili del nuovo tipo, e poi le usava in qualche modo, andava bene!
Si tratta solo di tradurre la definizione in Java:
crea un nuovo tipo Corso contenente: | componente String di nome .titolo | componente String di nome .docente | componente int di nome .anno | componente int di nome .ore
Solito metodo di traduzione:
class Corso { String titolo; String docente; int anno; int ore; }
Lo scriviamo su un file Corso.java
Tutti e due i file vanno compilati:
javac Corso.java javac Ing.java
Il primo file dice solo come sono fatti gli oggetti di tipo Corso, mentre il secondo è il programma. Quindi solo il secondo va eseguito:
java Ing
Questo fa capire a cosa serve il programma di esempio: con Corso.java da solo non potevo eseguire nessun programma.
Con il programma di esempio, ho un programma da eseguire per vedere se la definizione di tipo va bene.
Definire una classe per rappresentare triangoli.
Non servono altre specifiche.
Ogni oggetto è un triangolo
Nome della classe: Triangolo
Ogni triangolo è rappresentato da tre punti.
Quindi, ho tre componenti di tipo Point
Definizione del tipo:
crea nuovo tipo Triangolo con: | componente tipo Point di nome .primo | componente tipo Point di nome .secondo | componente tipo Point di nome .terzo
Basta che sia un qualsiasi programma che fa qualcosa su oggetti del tipo.
Per esempio, definire due triangoli, calcolare il perimetro del primo e l'area del secondo.
import java.awt.*; class PerArea { public static void main(String args[]) { Triangolo a; a=new Triangolo(); Triangolo b; b=new Triangolo(); a.primo=new Point(); a.primo.x=10; a.primo.y=20; a.secondo=new Point(); a.secondo.move(20,30); a.terzo=new Point(); a.terzo.move(15,20); int dx=a.primo.x - a.secondo.x; int dy=a.primo.y - a.secondo.x; double lato1; lato1=Math.sqrt(dx*dx+dy*dy); System.out.println(lato1); } }
Questo programma contiene solo il calcolo di un lato: il perimentro e l'area si calcolano nel solito modo.
Prima vediamo la definizione di tipo e poi facciamo commenti su questo programma.
La specifica informale era:
crea nuovo tipo Triangolo con: | componente Point di nome .primo | componente Point di nome .secondo | componente Point di nome .terzo
La traduzione avviene nel modo ovvio.
import java.awt.*; class Triangolo { Point primo; Point secondo; Point terzo; }
Regola generale:
Se og è una variabile di un tipo oggetto, e
.comp è una sua componente,
allora og.comp è una variabile.
Se og.comp è una variabile oggetto,
valgono tutte le regole degli oggetti
Nell'esempio, a.primo è una variabile
di tipo Point:
vale tutto quello che vale per le variabili Point
Dato che a.primo è una variabile di tipo Point
Per quello che riguarda il punto 3, ora vediamo l'evoluzione della memoria.
Triangolo a;
Produce il seguente stato della memoria:
Esiste solo la variabile, ma non l'oggetto.
Non esistono le variabili a.primo ecc.
a=new Triangolo();
La new crea effettivamente il nuovo oggetto:
Esistono le variabili a.primo ecc.
Importante: non esistono (ancora) gli oggetti punto!
Quindi, a.primo.x, a.primo.y, ecc. non esistono ancora
Fare a.primo.x=10; oppure a.primo.move(10,20)
a questo punto dà un errore
(prima di poter usare un oggetto, lo devo creare)
a.primo=new Point();
Questo crea effettivamente il punto.
Solo ora l'oggetto a.primo si può usare.
Ora si può fare a.primo.x=10 oppure a.primo.move(10,20)
Copiare= |
creare una nuova zona di memoria+ copiarci i dati della zona di memoria originaria. |
Dopo aver fatto:
Point p; p=new Point(); p.move(10,20);
Questo codice fa la copia
a.primo=new Point(); a.primo.move(p.x, p.y);
Questo invece indica lo stesso oggetto:
a.primo=p;
Prima:
Dopo aver fatto a.primo=p
Si tratta sempre dello stesso punto!
Se faccio p.x=12, viene modificato anche a.primo.x
Se copio con a.primo=new Point(); a.primo.move(p.x, p.y);:
La copia crea un nuovo oggetto punto
Non si può fare una cosa del genere:
// Codice errato import java.awt.*; class Triangolo { Point primo; primo=new Primo(); Point secondo; secondo=new Secondo(); Point terzo; terzo=new Terzo(); }
È una regola del linguaggio.
È possibile creare oggetti in una classe, ma soltanto nella definizione di un metodo.
In altre parole: si possono creare oggetti, ma non in questo modo.