Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack;...
-
Upload
caj-barbieri -
Category
Documents
-
view
229 -
download
2
Transcript of Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack;...
![Page 1: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/1.jpg)
type int_stack = struct {
int top;
int P[100]; }
int_stack creapila() {
int_stack s = new int_stack;
s.top = 0;
return s; }
int_stack push(int_stack s, int k) {
s.P[s.top]=k;
s.top=s.top+1;
return s; }
int top(int_stack s) {
return s.P[s.top]; }
int_stack pop(int_stack s) {
s.top = s.top-1;
return s; }
bool empty(int_stack s) {
return s.top=0; }
![Page 2: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/2.jpg)
il linguaggio che abbiamo scelto garantisce che quelli di prima sono i soli modi per manipolare la pila?
ad esempio, posso accedere alla rappresentazione della pila
int second_from_top(int_stack c) {
return c.P[c.top -1]; }
in generale: – i linguaggi possono astrarre sui dati (con i tipi)– il programmatore non può astrarre sui dati
![Page 3: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/3.jpg)
tipi di dato astratti (ADT):
meccanismo di astrazione che alcuni linguaggi mettono a disposizione, con queste caratteristiche
– un nome per il tipo– una implementazione per il tipo– un insieme di nomi di operazioni per manipolare il tipo– l’implementazione delle operazioni– una capsula che separi i nomi del tipo e delle operazioni dalle
loro implementazioni (la capsula si chiama signature, al suo interno stanno le implementazioni)
![Page 4: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/4.jpg)
abstype int_stack = {
type int_stack struct {
int P[100];
int n;
int top; }
signature
int_stack creapila()
int_stack push(int_stack s, int k)
int_stack pop(int_stack s)
empty(int_stack s)
int top(int_stack s)
operations
int top(int_stack s) { return s.P[s.top]; }
…
… }
posso creare una funzione second_from_top??
![Page 5: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/5.jpg)
distinzione fra interfaccia e implementazione
– fondamentale per le tecniche di sviluppo del software
– astrazione sul controllo: una funzione nasconde il codice che costituisce il suo corpo (l’implementazione), ma mostra la sua interfaccia
– astrazione sui dati: si nasconde come l’operazione è realizzata, ma anche come i dati sono rappresentati (information hiding)
conseguenza: posso sostituire l’implementazione di un ADT, senza cambiare l’interfaccia, e senza sperimentare nessun effetto osservabile nei programmi che usano quel tipo di dato astratto
![Page 6: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/6.jpg)
abstype int_stack = {
type int_stack struct {
int_stack next;
int info; }
signature
int_stack creapila()
int_stack push(int_stack s, int k)
int_stack pop(int_stack s)
empty(int_stack s)
int top(int_stack s)
operations
…
…
principio di indipendenza della rappresentazione
stessa signature, ma il tipo dello stack è diverso; le
operations saranno diverse
![Page 7: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/7.jpg)
vantaggi dei tipi di dato astratti
– incapsulamento e occultamento dell’informazione– dati e modi per manipolarli in un unico costrutto– metodologia per lo sviluppo strutturato del software
svantaggi dei tipi di dato astratti
– difficoltà di estensione o riuso delle astrazioni– alto costo di riuso ed estensione
![Page 8: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/8.jpg)
esempio: un ADT contatore
abstype Counter {type Counter = int;
signaturevoid reset (Counter x);int get (Counter x);void inc (Counter x);
operationsvoid reset (Counter x) {x=0;}int get (Counter x) {return x;}void inc (Counter x){x=x+1;}
}
modi per manipolare il contatore
definizione degli operatori
![Page 9: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/9.jpg)
esempio: un ADT contatore arricchito
abstype NewCounter1 {
type NewCounter1 = struct { int c; int num_reset = 0;}
signature
void reset (NewCounter1 x);
int get (NewCounter1 x);
void inc (NewCounter1 x);
int quanti_reset (NewCounter1 x);
operations
void reset (NewCounter1 x)
{ x.c=0;
x.num_reset=x.num_reset+1;}
int get (NewCounter1 x) {return x.c;}
void inc (NewCounter1 x) {x.c=x.c+1;}
int quanti_reset (NewCounter1 x) {return x.num_reset;} }
![Page 10: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/10.jpg)
abbiamo definito un nuovo ADT contatore arricchito, rispettando l’incapsulamento; ma
– devo ridefinire le operazioni già definite (overloading)– se ridefinisco l’implementazione di una operazione di
Counter, NewCounter1 non è modificato (devo farlo io)
seconda soluzione: posso usare Counter per definire un contatore arricchito?
![Page 11: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/11.jpg)
abstype NewCounter2 {
type NewCounter2 = struct { Counter c; int num_reset = 0;}
signature
void reset (NewCounter2 x);
int get (NewCounter2 x);
void inc (NewCounter2 x);
int quanti_reset (NewCounter2 x);
operations
void reset (NewCounter2 x)
{ reset(x.c);
x.num_reset=x.num_reset+1;}
int get (NewCounter2 x) {return get(x.c);}
void inc (NewCounter2 x) {inc(x.c);}
int quanti_reset (NewCounter2 x) {return x.num_reset;}
![Page 12: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/12.jpg)
abbiamo definito un nuovo ADT contatore arricchito, rispettando l’incapsulamento, partendo da Counter;
– le operazioni che non devo modificare sono richiamate all’interno di NewCounter2
– devo comunque definire esplicitamente le operazioni (get e inc) che non subiscono alcuna modifica; ci vorrebbe un modo automatico con cui ereditare da Counter l’implementazione delle operazioni
problema:
ho una serie di contatori, alcuni semplici e altri arricchiti, e voglio resettare tutti i valori
![Page 13: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/13.jpg)
Counter V[100];non posso immettere dei NewCounter2
NewCounter2 V[100];non posso immettere dei Counter
ma tutte le operazioni su un Counter sono anche possibili su un NewCounter2
serve una nozione di compatibilità di tipo come la seguente: T è compatibile con S se tutte le operazioni sui valori di S sono possibili sui valori di T
allora NewCounter2 è compatibile con Counter (e posso definire un Counter V[100] che contiene sia Counter che NewCounter2)
![Page 14: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/14.jpg)
for (int i=1; i<100; i++) reset (V[i]);
il risolutore dell’overloading interpreta (staticamente) l’operazione come un reset di Counter
– che fine fanno i campi num_reset dei newcounter2? – sono incrementati di 1? (no, ecco un altro problema)
la compatibilità ha risolto il problema di manipolare i due tipi, ma ha distrutto l’incapsulamento
abbiamo bisogno di una risoluzione dinamica del metodo reset
![Page 15: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/15.jpg)
concetti fondamentali che desideriamo realizzare
– incapsulamento ed astrazione dell’informazione– sottotipi (compatibilità fra tipi)– meccanismo di ereditarietà– selezione dinamica dei metodi in funzione del tipo
dell’argomento
![Page 16: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/16.jpg)
oggetto– capsula che contiene dati ed operazioni per manipolarli– fornisce una interfaccia per accedere all’oggetto
oggetto vs ADT– se dichiaro una variabile di un tipo astratto, la variabile
rappresenta solo i dati (che posso manipolare con le operazioni previste)
– invece, ciascun oggetto è un contenitore che incapsula dati e operazioni (con più o meno opacità)
– operazioni = METODI o FUNZIONI MEMBRO– dati = VARIABILI DI ISTANZA o DATI MEMBRO– l’esecuzione di una operazione è invocata mandando un
MESSAGGIO (nome del metodo + parametri); ad esempio:
oggetto.metodo(parametri)
![Page 17: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/17.jpg)
N.B. - l’oggetto che riceve i messaggio è un parametro implicito del messaggio stesso
i linguaggi a oggetti mettono a disposizione meccanismi di organizzazione degli oggetti (raggruppando tutti gli oggetti con la stessa struttura o struttura simile)
il meccanismo più usato è quello delle classi (ma ci sono linguaggi a oggetti senza classi)
classe– modello di un insieme di oggetti– fissa dati (tipo e visibilità), nome, signature, metodi
(visibilità e implementazione)– ogni oggetto appartiene ad almeno una classe
![Page 18: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/18.jpg)
class Counter {private int x;public void reset() {x=0;}public int get() {return x;}public void inc () {x=x+1;} }
Counter c = new Counter()Counter d = new Counter()
il codice dei metodi è memorizzatouna volta sola, nella classe
il codice del metodo deve accedere alla giusta variabile di istanza, che non è memorizzata nella classe, ma nell’istanza
dato visibile solo nella classe
metodi visibili da chiunque
istanziazione della classe per creare (dinamicamente) un
nuovo oggetto c e d
![Page 19: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/19.jpg)
una classe può essere istanziata con metodologie differenti:
– in Simula una classe è una procedura che restituisce un puntatore ad un RdA che contiene le variabili locali e le definizioni delle funzioni
– in Smalltalk una classe è uno schema per la definizione dell’implementazione di un insieme di oggetti
– in C++ e Java una classe è un tipo e tutti gli oggetti istanza della classe A sono valori di tipo A
![Page 20: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/20.jpg)
![Page 21: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/21.jpg)
i metodi della classe Counter si riferiscono alle singole variabili di istanza che eseguono il metodo (con THIS); quindi il legame fra metodo e oggetto è dinamico
ad esempio:
public void inc () {this.x = this.x+1;} }
alcuni linguaggi permettono di definire oggetti statici, memorizzati con la classe, quindi non accessibili con this
![Page 22: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/22.jpg)
linguaggi basati su delega (Self, Dylan, Javascript)
il meccanismo di organizzazione non è la classe, ma la delega; un oggetto demanda ad un altro (il genitore) l’esecuzione di un metodo.
un oggetto contiene – valori (dati o oggetti)– metodi– riferimenti ad altri oggetti (ai prototipi)
un messaggio è passato verso il genitore, fino a quello che lo comprende e che esegue il metodo;
![Page 23: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/23.jpg)
incapsulamento: definire un oggetto nascondendone una parte (dati o metodi)
vista della classe: pubblica (interfaccia) o privata
sottotipi: a una classe facciamo corrispondere l’insieme degli oggetti istanza della classe (tipo associato alla classe)
compatibilità:il tipo associato alla classe T è sottotipo di S se ogni messaggio compreso dagli oggetti di S è compreso anche dagli oggetti di T (oppure: T è sottotipo di S se l’interfaccia di S è un sottoinsieme dell’interfaccia di T)
![Page 24: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/24.jpg)
in C++ o Java: equivalenza per nome (e non strutturale)
(quindi la proprietà di “essere sottotipo” deve essere introdotta dal programmatore con le sottoclassi)
class NamedCounter extending Counter{
private string nome;
public void set_name(string n) {nome=n;}
public string get_name() {return nome;} }
Named Counter è una sottoclasse di Counter; le sue istanze contengono i campi di
Counter (quelli privati sono inaccessibili) e i nuovi campi
estende solo l’interfaccia, ma i metodi rimangono
gli stessi
![Page 25: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/25.jpg)
ridefinire un metodo (method overriding): partendo dal contatore ridefinisco un contatore esteso
class NamedCounter extending Counter{
private int num_reset;
public void reset() {
x=0;
num_reset= num_reset+1;}
public int quanti_reset() {return num_reset;} }
estende l’interfaccia e ridefinisce il metodo reset
![Page 26: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/26.jpg)
shadowing: ridefinire una variabile di istanza definita in una superclasse
class NewCounterPari extending NewCounter{
private int num_reset = 2;
public void reset() {
x=0;
num_reset= num_reset+2;}
public int quanti_reset() {return num_reset;} }
ridefinisce num_reset; ogni riferimento a num_reset in
questa classe si riferisce alla variabile locale, non a quella
di NrewCounter
![Page 27: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/27.jpg)
classi astratte: – figura solo il nome e il tipo di qualche metodo (il metodo
non è definito)– serve a fornire interfacce generiche, che saranno
ridefinite in altre classi derivate– Java = metodo astratto; C++ = pure virtual member
function
sottotipo: – ordine parziale sulle classi – oggetto massimo Object, su cui è definito un metodo di
clonazione e uno di uguaglianza (Java)
abstract class A { public int f(); }abstract class B { public int g(); }
class C extending A,B { private x=0; public int f() {return x;} public int g() {return x+1;} }
![Page 28: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/28.jpg)
costruttori: per creare un oggetto– allocare la memoria necessaria– inizializzare i dati
il costruttore è una parte di codice della classe che è eseguito al momento della creazione di una istanza;
problemi:– linguaggi con più costruttori– costruttori di superclassi (i dati non sono solo quelli
espliciti, ma anche quelli delle superclassi – constructor chaining in C++)
![Page 29: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/29.jpg)
ereditarietà: meccanismo che consente di definire nuovi oggetti a partire da (e riusando) oggetti già definiti
esempio: NewCounter eredita da Counter il dato x e i metodi inc e get, ma non il metodo reset (ridefinito)
ereditarietà diversa da sottotipo
riuso del codice che manipola un oggetto: è
una relazione fra implementazioni
uso di un oggetto in un altro contesto: è una
relazione fra interfacce
![Page 30: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/30.jpg)
sottotipo in Java– extends: definisce una sottoclasse– implements: una classe è dichiarata sottotipo di una o più
interfacce (come una classe virtuale)
ereditarietà in Java– extends, se la sottoclasse non ridefinisce un metodo
interface A { int f(); }interface B { int g(); }
class C { int x;int h() {return x+2; } }
class D extends C implements A,B {int f() {return x; } int g() {return x+1; } }
![Page 31: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/31.jpg)
sottotipo in C++– la definizione di classe derivata (sottoclasse) introduce la
relazione di ereditarietà;– essa introduce anche una relazione di sottotipo quando la
classe derivata dichiara come public la classe base;– in caso contrario, la classe derivata eredita da quella
base, ma non c’è relazione di sottotipo
class A { public: void f() {…}; … }
class B : public A {public: void g() {…}; }… }
class C : A {public: void h() {… }
… }
![Page 32: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/32.jpg)
ereditarietà e visibilità: – vista privata (nella classe)– vista pubblica (condivisa da tutti i clienti della classe)– vista protetta (una sottoclasse cha accede ai membri non
pubblici della superclasse)
ereditarietà singola: una classe può ereditare da una sola superclasse (la gerarchia è un albero)
ereditarietà multipla: una classe può ereditare da più superclassi (la gerarchia è un grafo)
problema: (name clash) una classe C eredita da classi A e B lo stesso metodo (con la stessa signature)
![Page 33: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/33.jpg)
class A { int x;
int f () { return x;}
class B { int y;
int f () { return y;}
Class C extending A,B { int h () { return f()} }
quale dei due metodi è ereditato da C??
– divieto sintattico di conflitto– risoluzione esplicita (A::f() oppure B::f() – soluzioni C++)– risoluzione convenzionale (ordine di definizione)– problema del diamante
![Page 34: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/34.jpg)
selezione dinamica dei metodi (dispatch):
un metodo definito per un oggetto può essere ridefinito (overridden) su oggetti il cui tipo è sottotipo dell’oggetto originale.
o.m(parametri)
la selezione avviene a runtime, in base al tipo dell’oggetto che riceve il messaggio,
e non in base al tipo del nome dell’oggetto (informazione statica)
quale versione di m è selezionata??
![Page 35: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/35.jpg)
class Counter {
private int x;
public void reset() {x=0;}
public int get() {return x;}
public void inc () {x=x+1;} }
class NewCounter extending Counter{
private int num_reset = 0;
public void reset () {x=0; num_reset= num_reset+1}
public int quanti_reset () {return num_reset} }
overriding di reset nella classe derivata
![Page 36: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/36.jpg)
eseguiamo il codice:
NewCounter n = new Counter();
Counter c;
c = n;
c.reset
il tipo statico del nome c è Counter
c si riferisce ad una istanza di NewCounter
il metodo invocato è quello di NewCounter
![Page 37: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/37.jpg)
Counter V[100];
for (int i=0; i<100; i++) V[i].reset();
se in counter sono memorizzati sia dati di tipo
Counter che dati di tipo NewCounter,
la selezione dinamica assicura che ogni volta sia chiamato il
reset giusto.
![Page 38: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/38.jpg)
la selezione dinamica dei metodi lavora anche quando un metodo di un oggetto invoca un metodo dello stesso oggetto
class A { int a = 0;
void f() { g() };
void g() { a=1;} }
class B extending A { int d=0;
void g() { d=2;} }
se b è istanza di B, e se invoco su b il metodo f() che B eredita da A
f() invoca a sua volta g(), quale versione di g() è eseguita??
g() definito dentro A
g() ridefinito dentro B
![Page 39: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/39.jpg)
FINO QUI aspetti implementativi: oggetti
un oggetto (istanza di una classe) è rappresentato come un record, con
– tanti campi quante sono le variabili di istanza – più le variabili della superclasse
in caso di shadowing (lo stesso nome appare in una classe e nella sottoclasse) nell’oggetto ci sono più campi, ciascuno corrisponente a una dichiarazione
l’oggetto contiene un puntatore al descrittore della classe di cui è istanza
![Page 40: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/40.jpg)
aspetti implementativi: classi ed ereditarietà
gerarchia di classi rappresentata come lista concatenata
![Page 41: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/41.jpg)
aspetti implementativi: late binding di self
un metodo è eseguito come una funzione (sullo stack è posto un rda con le variabili locali, i parametri, ecc.)
differenza: il metodo deve accedere alle variabili di istanza dell’oggetto su cui è invocato (che non è noto al momento della compilazione); è nota però la struttura dell’oggetto (che dipende dalla classe)
quando un metodo è invocato, gli viene passato anche un puntatore all’oggetto che ha ricevuto il metodo; durante l’esecuzione del metodo il puntatore è il this del metodo
![Page 42: Type int_stack = struct { int top; int P[100]; } int_stack creapila() { int_stack s = new int_stack; s.top = 0; return s; } int_stack push(int_stack s,](https://reader036.fdocuments.in/reader036/viewer/2022062319/5542eb58497959361e8c41d1/html5/thumbnails/42.jpg)
aspetti implementativi: ereditarietà singola
se il tipaggio è statico allora è noto a compile-time l’insieme dei metodi che possono essere inviati a un oggetto