Un linguaggio a oggetti Java Oggetti Un oggetto

  • Slides: 16
Download presentation
Un linguaggio a oggetti: Java

Un linguaggio a oggetti: Java

Oggetti Un oggetto consiste di uno stato e delle operazioni per trasformarlo. Un linguaggio

Oggetti Un oggetto consiste di uno stato e delle operazioni per trasformarlo. Un linguaggio è orientato a oggetti se i programmi esprimono costruzione e manipolazione di oggetti. Esempi Simula 67, CLU, Small. Talk, Java

Programmi in Java (1) I programmi in Java consistono di classi e di interfacce.

Programmi in Java (1) I programmi in Java consistono di classi e di interfacce. Le classi consentono di definire collezioni di procedure (metodi) e tipi di dato. Le interfacce consentono di definire tipi di dato. Classi e interfacce possono essere raggruppate in package. Esempio Una classe che definisce una collezione di procedure public class Num { public static int gcd (int n, int d) { // REQUIRES: n, d > 0 while (n != d) if (n > d) n = n - d; else d = d - n; return n; } public static boolean is. Prime (int p) { // implementazione} } Procedure della classe possono essere invocate cosí: int x = Num. gcd (15, 6); if (Num. is. Prime (y)) … ;

Programmi in Java (2) Classi e interfacce sono raggruppate in package. Scopo dei package:

Programmi in Java (2) Classi e interfacce sono raggruppate in package. Scopo dei package: Fornire un meccanismo di incapsulamento. Classi e interfacce del package possono essere usate dal codice in un altro package solo se dichiarate public. Classi e interfacce hanno un nome relativo al package.

Variabili (1) Ai dati si accede per mezzo di variabili. Ogni variabile ha una

Variabili (1) Ai dati si accede per mezzo di variabili. Ogni variabile ha una dichiarazione che ne indica il tipo. Variabili di tipo primitivo (es. Int, bool) contengono valori e risiedono sulla pila run-time nello spazio allocato alla chiamata del metodo che le dichiara. Variabili degli altri tipi contengono riferimenti a oggetti che stanno sullo heap. Vengono create mediante costruttori. Variabili possono essere inizializzate quando sono dichiarate e devono essere inizializzate prima dell’uso.

Variabili (2) Esempio int i = 6; int j; // non inizializzata int [

Variabili (2) Esempio int i = 6; int j; // non inizializzata int [ ] a = {1, 3, 5, 7, 9}; // crea un array di cinque elementi int b new int [3]; string s = “abcdef”; //crea una nuova string t = null; L’effetto sulla pila e sullo heap è il seguente: i j a b s t 6 [1, 3, 5, 7, 9] [0, 0, 0] “abcdef”

Assegnamenti e confronti Un assegnamento v = e copia nella variabile v il valore

Assegnamenti e confronti Un assegnamento v = e copia nella variabile v il valore ottenuto valutando l’espressione e. Se e valuta al riferimento a un oggetto il riferimento viene copiato nella variabile Esempio L’esecuzione degli assegnamenti j = i; b = a; t = s; porta la situazione dell’esempio precedente nella situazione: i 6 j 6 a [1, 3, 5, 7, 9] b [0, 0, 0] s “abcdef” t L’operatore == consente di determinare se due variabili contengono lo stesso valore. Per determinare se non contiene nessun valore v == null.

Oggetti mutabili e immutabili Stringhe sono immutabili. La concatenazione di stringhe non modifica gli

Oggetti mutabili e immutabili Stringhe sono immutabili. La concatenazione di stringhe non modifica gli argomenti e restituisce una nuova stringa. Array sono mutabili. L’assegnamento all’i-esimo elemento dell’array muta l’elemento specifico dell’oggetto Esempio L’esecuzione degli assegnamenti t = t + “g”; b[0] = 6; porta la situazione dell’esempio precedente nella situazione: i j a b s t 6 6 [6, 3, 5, 7, 9] [0, 0, 0] “abcdef” “abcdefg”

Chiamate di metodi (1) Sintassi metodo e. m (arg 1, …, argk) classe parametri

Chiamate di metodi (1) Sintassi metodo e. m (arg 1, …, argk) classe parametri attuali Esecuzione vengono trovati metodo e classe che lo definisce viene messo sulla pila un record di attivazione con spazio per i parametri e quanto richiesto dal metodo vengono valutati i parametri attuali e il valore messo sulla pila nello spazio loro riservato viene passato il controllo al metodo

Chiamate di metodi (2) Esempio … public static void multiplies (int [ ] a,

Chiamate di metodi (2) Esempio … public static void multiplies (int [ ] a, int m) { if (a == null) return; for (int i = 0; i < a. length; i++; a[i] = a[i] + m; }. . . int [ ]b = {1, 3, 5, 7, 9}; Arrays. multiplies (b, 2); b [1, 3, 5, 7, 9] b a m 2 [1, 3, 5, 7, 9] b [2, 6, 10, 14, 18]

Tipi e gerarchie di tipi (1) Java è fortemente tipato ossia il compilatore di

Tipi e gerarchie di tipi (1) Java è fortemente tipato ossia il compilatore di Java può verificare che ogni assegnamento e ogni chiamata di metodo siano corretti riguardo al tipo. Esempio int y = 7; int z = 3; int x = Num. gcd (z, y); Num. gcd si apetta due interi e restituisce un intero. Perciò la chiamata e l’assegnamento sono corretti.

Tipi e gerarchie di tipi (2) Un tipo può avere sottotipi. La relazione di

Tipi e gerarchie di tipi (2) Un tipo può avere sottotipi. La relazione di sottotipo è riflessiva e transitiva. Se S è un sottotipo di T gli oggetti di tipo S possono essere usati in ogni contesto che si aspetti oggetti di tipi T, in particolare gli oggetti di tipi S possono usare tutti i metodi definiti per gli oggetti di tipo T. Esempio Object è un tipo di cui tutti gli oggetti sono sottotipo. Quindi se a Array, s String si può avere Object o 1 = a; Object o 2 = s;

Controllo del tipo e casting Il controllo del tipo si basa sul tipo apparente.

Controllo del tipo e casting Il controllo del tipo si basa sul tipo apparente. Se si vuole un controllo sul tipo effettivo occorre il casting Esempio Se s è di tipo string il tipo effettivo di o 2 dopo l’assegnamento Object o 2 = s; è String anche se il tipo apparente rimane Object ha il metodo boolean equals (Object o) quindi è corretto if o 2 equals (“abc”) ma non if (o 2. length( )) perché length si aspetta una stringa Il casting inpone un controllo run-time sul tipo. Esempio if ((String) o 2. length()) è corretto

Conversioni implicite e overloading Java consente conversioni implicite Esempio char c = “a”; int

Conversioni implicite e overloading Java consente conversioni implicite Esempio char c = “a”; int n = “c”; Java consente overloading Esempio static int comp (int, long) //defn 1 static int comp (long, int) //defn 2 static int comp (long, long //defn 3 Siano metodi di una classe c. Si abbia int x; long y; float z; La chiamata c. comp (x, y) si accorda sia con defn 1 che con defn 2. Quando una chiamata si accorda con più di una definizione si sceglie la definizione più specifica, dove m 1 è più specifica di m 2 se una chiamata legale di m 1 sarebbe anche una chiamata legale di m 2 fatte le opportune conversioni. Esempio per c. comp (x, y) si sceglie defn 1 perchè più specifica di defn 2

Scelta a run-time del metodo appropriato Occorre talora provvedere che a run-time si scelga

Scelta a run-time del metodo appropriato Occorre talora provvedere che a run-time si scelga il metodo appropriato ai tipi effettivi degli oggetti Esempio Se si ha String t = “ab”; Object o = t + “c”; String r = “abc”; boolean b = o. equals(r); Per ottenere che vengano confrontate le stringhe in o e in r (e non gli oggetti che sono differenti) occorre che la rappresentazione dell’oggetto nello heap contenga un’entrata per ciascuno dei metodi dell’oggetto. Nell’esempio il codice per il confronto di uguaglianza dovrà essere quello dell’uguaglianza di stringhe. o r <“abc”, > equals codice per l’uguaglianza di stringhe

Wrapping I tipi primitivi come int e char non sono sottotipi di Object e

Wrapping I tipi primitivi come int e char non sono sottotipi di Object e i loro valori non possono essere usati in contesti dove sono richiesti oggetti di tipo Object (per esempio non possono essere memorizzati in elementi di oggetti di tipo Vector (vettori di oggetti). Si ricorre a metodi costruttori che avviluppano (wrap) gli oggetti di tipo primitivo facendone oggetti e metodi che fanno le trasformazioni inverse Esempio vector v = new Vector ( ); // crea un nuovo vettore vuoto if v. size( ) == 0) // è vero v. add (“abc”); // aggiunge un nuovo elemento al vettore String s = (String) v. get (0); // assegna a s il primo elemento nel tipo attuale v. set (0, “def”); // aggiorna il primo elemento v. set (1, Integer(x)); // si assume che x sia di tipi int y = ((Integer) v. get(2). int. Value; \ si fà prima il casting dell’oggetto in Integer e poi la trasformazione in int