Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.

Slides:



Advertisements
Presentazioni simili
Programmazione ad oggetti
Advertisements

Costruttori e Distruttori
Recupero debito quarto anno Secondo incontro
Informatica Recupero debito quarto anno Terzo incontro.
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
1 Semantica Operazionale di un frammento di Java: lo stato.
Classi ed Oggetti in Java (Cenni). Richiami Ruolo delle Classi in Java Oggetti.
Liste di Interi Esercitazione. Liste Concatenate Tipo di dato utile per memorizzare sequenze di elementi di dimensioni variabile Definizione tipicamente.
Le gerarchie di tipi.
LIP: 19 Aprile Contenuto Soluzione Compitino Tipo di dato MultiSet, estensione con sottoclasse.
Semantica Operazionale di un frammento di Java: lo stato
Liste Ordinate 3 Maggio Ultima Lezione Abbiamo visto i tipi di dato astratti IntList e StringList Realizzano liste di interi e di stringhe Realizzati.
LIP: 1 Marzo 2005 Classe Object e Vettori. Partiamo da Lesercizio dellultima esercitazione realizzato tramite array Vedremo come si puo fare in modo piu.
Fondamenti di Informatica
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
1 Lezione XIII Lu 17-Nov-2005 Programmare le classi.
Derivazione tra classi
Overriding.
Approfondimento delle classi
1 Le gerarchie di tipi. 2 Supertipi e sottotipi 4 un supertipo –class –interface 4 può avere più sottotipi –un sottotipo extends il supertipo ( class.
Java base IV: Java e la programmazione O.O.
IL TEMA DELLA RIUSABILITÀ Si vuole riusare tutto ciò che può essere riusato (componenti, codice, astrazioni) Non è utile né opportuno modificare codice.
IL TEMA DELLA RIUSABILITÀ Si vuole riusare tutto ciò che può essere riusato (componenti, codice, astrazioni) Non è utile né opportuno modificare codice.
Elementi di programmazione ad oggetti a. a. 2009/2010 Corso di Laurea Magistrale in Ingegneria Elettronica Docente: Mauro Mazzieri, Dipartimento di Ingegneria.
Programmazione in Java (8)
AlgoLab - Ereditarieta' Ereditarietà e polimorfismo in Java Laboratorio di Algoritmi 02/03 Prof. Ugo de Liguoro.
I Metodi in Java Il termine "metodo" è sinonimo di "azione". Quindi, affinché un programma esegua qualche istruzione, deve contenere metodi.
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
Enumerazioni e Classi 1. Enumerazioni Permettono di definire nuovi tipi che consistono in un insieme di valori costanti (ognuno con un nome) – Migliorano.
Fopndamenti di programmazione. 2 La classe String Una stringa è una sequenza di caratteri La classe String è utilizzata per memorizzare caratteri La classe.
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA FINALE DEL 21 MAGGIO 2007 NOME: COGNOME: ________________________________________________________________________________.
Corso JAVA Lezione n° 12 Istituto Statale di Istruzione Superiore “F. Enriques”
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
Fondamenti di Informatica 2 Ingegneria Informatica Docente: Giovanni Macchia a.a
Oggetti in C# Lezione 5 Polimorfismo I Andrea Zoccheddu.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Esercitazione su Vector. Permette di definire collezioni di dati generiche, che sono in grado di memorizzare elementi di ogni sottotipo di Object Definito.
1 Osservazioni Generali Struttura di programma Gerarchia di classi: overloading, overriding, e dispatching Analisi ed esecuzione Modificabilità e condivisione.
Fondamenti di Informatica II Ingegneria Informatica Prof. M.T. PAZIENZA a.a – 3° ciclo.
1 Eccezioni in Java. 2 Ricordiamo che 4 una procedura può terminare –normalmente, ritornando un risultato –in modo eccezionale ci possono essere diverse.
Fondamenti di informatica Oggetti e Java Luca Cabibbo Luca Cabibbo – Fondamenti di informatica: Oggetti e Java Copyright © 2004 – The McGraw-Hill Companies.
estensione (con piccole varianti) di quella in
1 Semantica Operazionale di un frammento di Java: le regole di transizione estensione (con piccole varianti) di quella in FONDAMENTI DI PROGRAMMAZIONE.
Esercitazione Object, Vettori, Liste. Ereditarieta’ Abbiamo visto come tramite l’ereditarieta’ e’ possibile estendere classi esistenti -arricchendo lo.
Ese 1 (del 31 Marzo 2004). Il compilatore Non esegue il programma, non guarda i valori che possono assumere di volta in volta le variabili, non fa assunzioni.
LIP: 9 Maggio Esercizi Riprendiamo un esercizio proposto Definire un tipo di dato Persona che definisce oggetti che rappresentano le informazioni.
Programmazione in Java. Classi I programmi in Java consistono di classi. Le classi consentono di definire: collezioni di procedure (metodi statici) tipi.
1 Semantica Operazionale di un frammento di Java: le regole di transizione estensione (con piccole varianti) di quella in Barbuti, Mancarella, Turini,
1 Semantica Operazionale di un frammento di Java: le regole di transizione estensione (con piccole varianti) di quella in Barbuti, Mancarella, Turini,
LIP: 8 Marzo 2005 Vettori. Abbiamo visto L’uso di Vector come alternativa all’uso di arrays Rivediamo l’esercizio dell’altra volta.
Esercitazione del 7 marzo 2008 Ereditarieta’. Esercizio: soluzione Implementare la seguente specifica che definisce un tipo di dato Libro.
Cose nuove di Java (prima a chiacchiera, poi formalmente)
LIP: 2 Maggio 2008 Classi Astratte. Cos’e’ una Classe Astratta una classe astratta e’ un particolare tipo di classe permette di fornire una implementazione.
Ereditarieta’. Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire.
Sommario Oggetti immutabili e non Tipi Primitivi: String, Arrays.
Progettare una classe 21 Febbraio La classe BankAccount Vogliamo realizzare una classe i cui oggetti sono dei semplici conti bancari. * Identifichiamo.
Classi ed Oggetti in Java (Cenni). Richiami Cenni sull’ Implementazione, Macchine Astratte, Compilatore, Interprete Ruolo delle Classi in Java Oggetti.
Alcune Classi Standard Object, Vettori. Ereditarieta’ Abbiamo visto come tramite l’ereditarieta’ e’ possibile estendere classi esistenti -arricchendo.
LIP: 11 Maggio 2007 Classi Astratte. Cos’e’ una Classe Astratta una classe astratta e’ un particolare tipo di classe permette di fornire una implementazione.
Esercitazione del 9 marzo 2007 Ereditarieta’. Richiami Definire sottoclassi (ereditarieta’) Overriding Specificatori di accesso (private, protected) Principio.
1 Semantica Operazionale di un frammento di Java: intro estensione (con piccole varianti) di quella di FP | v |
1 Semantica Operazionale di un frammento di Java: intro estensione (con piccole varianti) di quella di FP | v |
LIP: 4 Maggio 2007 Interfacce. Cos’e’ una Interfaccia una interfaccia e’ un particolare tipo di classe contiene solo la specifica non ha implementazione.
LIP: 15 Marzo 2005 Vettori di interi. Esercizio proposto Definire una classe VectorInt i cui oggetti sono vettori omogenei di interi ordinati in modo.
LIP: 18 Aprile 2008 Interfacce. Rappresentazione Lista val next vuota Lista vuota: any true Lista non vuota: any true 154 false 24 false.
Corso di Algoritmi e Strutture Dati con Laboratorio Richiami di Java – parte II.
Introduzione all’Ereditarietà Pietro Palladino. Richiami UML Classe: descrizione di un insieme di oggetti software con caratteristiche simili Definisce.
Tecnologia OO.
Transcript della presentazione:

Ereditarieta’

Contenuti Introduciamo un meccanismo fondamentale di Java: l’ereditarieta’ Permette di estendere classi gia’ definite (ovvero di definire sottotipi di tipi gia’ definiti) Introduciamo i meccanismi principali (l’utilizzo dell’ereditarieta’ lo riprenderemo in seguito)

Ricordiamo che I programmi in Java consistono di classi. Le classi consentono di definire: collezioni di procedure (metodi statici) come prototipi di oggetti (tramite variabili e metodi d’istanza, che definiscono il loro stato interno e le operazioni)

Ricordiamo che…… Variabili e metodi statici appartengono alla classe Variabili e metodi di istanza appartengono agli oggetti (istanze della classe). Una classe definisce un tipo (nome della classe). Gli oggetti istanza della classe hanno quel tipo.

L’ ereditarieta’ è un meccanismo fondamentale sia per il riutilizzo del codice che per lo sviluppo incrementale di programmi. Questo meccanismo permette di estendere e potenziare classi già esistenti fattorizzare informazioni comuni a piu’ classi Ereditarietà

Supponiamo di volere definire una classe i cui oggetti hanno una struttura più ricca di quella di una classe già definita una classe che realizza delle funzionalità aggiuntive rispetto ad una classe già definita In questi casi si può definire la nuova classe come sottoclasse della precedente, ereditando le caratteristiche gia’ presenti. A cosa serve

Supponiamo di avere definito una classe Persona gli oggetti della classe memorizzano il nome e l’indirizzo semplici operazioni definite tramite metodi d’istanza Esempio

public class Persona { public String nome; public String indirizzo; public Persona() {this.nome = ""; this.indirizzo = ""; } public Persona(String nome,String indirizzo) {this.nome = nome; this.indirizzo = indirizzo; } public String getNome() {return nome; } Esempio di classe 1

public String getIndirizzo() {return indirizzo; } public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); } public boolean omonimo(Persona p) {return this.nome.equals(p.nome); } Esempio di classe 2

Vogliamo definire una classe Studente che rappresenti gli studenti iscritti ad un corso di laurea. Ogni studente è descritto dal nome, dall'indirizzo, dal numero di matricola e dal piano di studio. Vogliamo delle operazioni addizionali per leggere e modificare il piano di studio Uno Studente è un tipo particolare di Persona. Esempio di sottoclasse 1

L'ereditarietà ci consente di definire la classe Studente senza ripetere la descrizione di tutte le variabili e i metodi di Persona Definiamo Studente in modo incrementale, come sottoclasse Esempio di sottoclasse 1

public class Studente extends Persona { public int matricola; public String pianoDiStudio; public static int nextMatricola = 1; public Studente() { this.matricola = nextMatricola; nextMatricola=nextMatricola+1; this.pianoDiStudio = ""; } public Studente(String nome, String indirizzo) {this.nome = nome; this.indirizzo = indirizzo; this.matricola = nextMatricola; nextMatricola= nextMatricola+1; this.pianoDiStudio = ""; } Esempio di sottoclasse 2

public String getPdS() {return pianoDiStudio; } public void modificaPdS(String nuovoPdS) { pianoDiStudio += nuovoPdS + "\n"; } Esempio di sottoclasse 3

La parola chiave extends significa che Studente è una sottoclasse o classe derivata di Persona Persona è una superclasse o classe genitrice di Studente Analogamente Studente è un sottotipo di Persona

Se c1 è una sottoclasse di (estende) c2 le variabili e metodi statici di c2 (e delle sue superclassi) sono visibili direttamente da c1 variabili e metodi di istanza di c2 (e delle sue superclassi) diventano anche variabili e metodi di istanza di c1 (a meno di overriding) Semantica informale

Un oggetto di tipo Studente avrà quattro variabili di istanza: * nome e indirizzo ereditate da Persona * matricola e pianoDiStudio definite nella sottoclasse Studente inoltre avra’ tutti i metodi d’istanza della sottoclasse e della superclasse (a meno di sovrascrittura) per quanto riguarda le variabili ed i metodi statici dichiarati nella superclasse (non ce sono..) possono essere usati come se fosse un oggetto di tipo Persona

Un oggetto di tipo Studente

Esempio Studente p= new Studente(); String s1= p.getIndirizzo(); (metodo della superclasse) String s2=p.getPds(); (metodo della sottoclasse) String s3=p.nome; (variabile della superclasse) int x=p.matricola; (variabile della sottoclasse) Le variabili sono pubbliche (non ci sono vincoli per l’accesso)

Anche per i costruttori esiste un meccanismo di ereditarietà: all’atto della creazione di un oggetto della sottoclasse c1 viene eseguito automaticamente il costruttore della superclasse c2 (per inizializzare le variabili ereditate) Costruttori

Esempio: costruttori public Studente() { this.matricola = nextMatricola ++; this.pianoDiStudio = ""; } public Persona() {this.nome = ""; this.indirizzo = ""; } quando viene eseguito new Studente() il costruttore di Persona viene invocato automaticamente per inizializzare le variabili eredidate alla stringa vuota possibile per i costruttori di default (che non hanno parametri)

Altrimenti… public Studente(String nome, String indirizzo) {this.nome = nome; this.indirizzo = indirizzo; this.matricola = nextMatricola; nextMatricola= nextMatricola+1; this.pianoDiStudio = ""; } Le variabili ereditate vanno inizializzate esplicitamente assegnando i valori dei parametri

In alcuni casi i metodi ereditati dalla superclasse possono non essere adatti per la sottoclasse Una sottoclasse puo’ sovrascrivere (dichiarare) un metodo della superclasse (stesso nome, stessi parametri, stesso tipo) In tal caso sugli oggetti della sottoclasse viene utilizzato il metodo riscritto (quello piu’ specifico) Overriding

Ad esempio, se invochiamo il metodo visualizza su un'istanza di Studente, verranno stampati solo i valori delle prime due variabili d'istanza (nome e indirizzo). public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); }

Se vogliamo stampare anche la matricola ed il piano di studio, dobbiamo sovrascrivere (override) visualizza aggiungendo a Studente la dichiarazione del seguente metodo: public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); System.out.println("Matricola: " + matricola + "\nPianodiStudio: " + pianoDiStudio); }

Il comando p.visualizza() invocherà il metodo visualizza della classe Persona se p è un'istanza di Persona il nuovo metodo che stampa anche il numero di matricola e il piano di studio se p è un'istanza di Studente. La scelta del metodo piu’ specifico viene effettuata a tempo di esecuzione in base al tipo di p Non puo’ essere fatta a tempo di compilazione (come vedremo a causa dei sottotipi)

Ricordiamo che le variabili private sono visibili solo nella classe in cui sono dichiarate Se nella classe Persona avessimo dichiarato le variabili d'istanza private, non sarebbe stato possibile accedere dalla sottoclasse alle variabili private dichiarate nella superclasse. Specificatori di accesso : private e public

Gli oggetti di tipo Studente possiedono le variabili della superclasse (le ereditano) Ma non possono accedervi! Il codice della sottoclasse non va bene: problemi nei costruttori e nel metodo visualizza() (sovrascritto) Variabili della superclasse private

Il metodo visualizza di Studente avrebbe causato un errore in compilazione, tentando di accedere a variabili private dichiarate nella superclasse. public void visualizza() {System.out.println("Nome: " + nome + "\nIndirizzo: " + indirizzo); System.out.println("Matricola: " + matricola + "\nPianodiStudio: " + pianoDiStudio); } Problema I

Problema II public Studente(String nome, String indirizzo) {this.nome = nome; this.indirizzo = indirizzo; this.matricola = nextMatricola; nextMatricola= nextMatricola+1; this.pianoDiStudio = ""; }

Allora come avrebbe fatto un oggetto di tipo Studente a modificare le variabili d’istanza ereditate dalla superclasse? Si puo’ accedere alle variabili attraverso i metodi ed i costruttori della superclasse utilizzando super super (simile a this) fa riferimento all'istanza che sta eseguendo un metodo o un costruttore, ma costringe l'interprete a vedere l'oggetto come istanza della superclasse. Super

Riscriviamo il metodo visualizza per Studente in modo da chiamare il metodo visualizza di Persona per accedere alle variabili della superclasse public void visualizza() { super.visualizza(); System.out.println("Matricola: " + matricola + "\nPianodiStudio: " + pianoDiStudio); } Il metodo fa la stessa cosa di prima, ma lo fa in modo diverso! Esempio 1

Riscriviamo il costruttore in modo da chiamare il costruttore superclasse public Studente(String nome, String indirizzo) {super(nome,indirizzo); this.matricola = nextMatricola; nextMatricola= nextMatricola+1; this.pianoDiStudio = ""; } Esempio 2

Gerarchia di Tipi La relazione di sottoclasse e’ transitiva Si crea una gerarchia di classi (o di tipi) al cui top c’e’ la classe primitiva Object Tutti i tipi che definiamo sono per default sottotipi di Object

Grazie all’ereditarieta’ i sottotipi supportono il comportamento del supertipo, ovvero le istanze della sottoclasse hanno le variabili d’istanza ed i metodi (al limite overridden) del supertipo hanno accesso alle variabili ed ai metodi statici della superclasse Di conseguenza un oggetto del sottotipo può essere utilizzato dovunque sia richiesto un oggetto del supertipo. Principio di sostituzione

Persona tizio = new Studente("Mario Rossi", "Pisa"); /* corretto: su tizio posso invocare tutti i metodi di Persona, grazie all'ereditarieta' */ tizio.visualizza() ; tizio.nome=“Francesca”; Esempio 1 Un'istanza di Studente si può usare in qualsiasi espressione, dove sia richiesto un oggetto di Persona, come in un assegnamento o nel passaggio dei parametri.

Un'istanza di Studente si può usare dovunque sia richiesto un oggetto di Persona, come in un assegnamento o nel passaggio di parametri. Persona tizio = new Persona("Marco Rossi", "Pisa"); Studente pippo = new Studente("Mario Rossi", "Pisa"); /* corretto: omonimo richiede un parametro di tipo Persona */... if(tizio.omonimo(pippo))... Esempio

Non è possibile il contrario, ovvero utilizzare un oggetto del supertipo al posto di uno del sottotipo. Il sottotipo puo’ avere variabili e metodi (d’istanza o statici) aggiuntivi, per esempio il numero di matricola o il metodo che ritorna il piano di studio.... Attenzione

... Studente tizio = new Persona("Mario Rossi", "Pisa"); String s=tizio.getpdS(); L’oggetto associato alla variabile tizio e’ di tipo Persona, non possiede il metodo getPdS() Per evitare errori a run-time, questo e’ un errore di tipo rilevato staticamente dal compilatore!!!! Esempio

Il principio di sostituzione e’ fondamentale per sfruttare i sottotipi Permette di riusare tutto il codice definito per il supertipo per tutti i sottotipi Permette di realizzare una sola volta operazioni comuni tra vari sottotipi Nel seguito vedremo di capire meglio perche’, per ora vediamo un esempio... Flessibilita’

public boolean omonimo(Persona p) {return this.nome.equals(p.nome); } omonimo richiede un parametro di tipo Persona, grazie al principio di sostituzione lo possiamo usare anche per il sottotipo (altrimenti avremmo dovuto ridefinirlo) Studente tizio = new Studente("Marco Rossi", "Pisa"); Studente pippo = new Studente("Mario Rossi", "Pisa"); if(tizio.omonimo(pippo))

Il principio di sostituzione crea pero’ dei problemi per i controlli statici dovuti alla presenza dei sottotipi Tipo apparente : tipo con cui una variabile e’ dichiarata Tipo effettivo: tipo del valore legato alla variabile Il tipo apparente ed il tipo effettivo possono essere diversi, in particolare il tipo effettivo puo’ essere un sottotipo del tipo apparente... Tipo apparente e tipo effettivo

Persona tizio = new Studente("Mario Rossi", "Pisa”); tizio ha tipo apparente Persona tipo effettivo Studente... Esempio

Il compilatore? Il controllo dei tipi in Java e’ effettuato staticamente dal compilatore (non a run-time) Il compilatore di Java effettua una analisi statica, ovvero una verifica sul codice del programma, che esamina tutte le istruzioni separatamente e controlla che ogni assegnamento e ogni chiamata di metodo (passaggio di parametri) sia corretta rispetto ai tipi delle variabili

Tipo Apparente Come fa il compilatore a usare il tipo effettivo di una variabile senza eseguire un programma? Non puo’ (dipende dal flusso di esecuzione) calcolare il tipo del valore associato ad una variabile Di consequenza il controllo dei tipi fatto dal compilatore usa solo il tipo apparente

Persona tizio = new Studente("Mario Rossi", "Pisa"); tizio.modificaPdS("Algebra"); Si verifica un errore di compilazione. Infatti abbiamo chiamato su tizio (variabile dichiarata di classe Persona ) un metodo della sottoclasse Studente. Anche se il tipo effettivo sarebbe giusto……il compilatore non lo conosce! E’ possibile che staticamente si rilevino errori di tipo che non sarebbero tali a run-time (ovvio) Attenzione

((Sottotipo) espressione) il compilatore tratta espressione come se fosse del Sottotipo (si fida) Il controllo che il tipo effettivo di espressione sia Sottotipo e’ rimandato a run-time (errore a tempo di esecuzione) Il Cast: spostare il controllo a run-time

Persona tizio = new Studente("Mario Rossi", "Pisa"); ((Studente)tizio).modificaPdS("Algebra"); non ci sono errori in fase di compilazione, il compilatore verifica solo che il tipo apparente di tizio sia supertipo di Studente (tipo verso il quale facciamo il cast) tratta nella chiamata di metodo tizio come se fosse del sottotipo Esempio di Cast

Quando si valuta ((Studente) tizio) se tizio non ha tipo effettivo Studente, verrà invece sollevata una eccezione a run-time (ClassCast) Persona tizio = new Studente("Mario Rossi","Pisa"); ((Studente)tizio).modificaPdS("Algebra"); non ci sono errori in fase di esecuzione in questo caso!!! il cast e’ molto utile, come vedremo indispensabile per programmare A run-time

Si può controllare la classe di appartenenza di un oggetto prima del cast: if (tizio instanceof Studente) ((Studente) tizio).modificaPdS("Algebra"); La condizione (obj instanceof Classe) restituisce true se e solo se obj è una istanza della classe Classe. Controllo del tipo di un oggetto

Tipo effettivo e apparente:conseguenza Il controllo dei tipi statico non evita errori di tipo a run-time a causa dei cast La scelta del metodo piu’ specifico tra metodi overridden dipende dal tipo effettivo (deve essere fatta a run-time)

Esempio Supponiamo di avere riscritto il metodo visualizza nella sottoclasse studente Persona tizio = new Studente("Mario Rossi", "Pisa"); tizio.visualizza(); Compila correttamente Deve invocare il metodo piu’ specifico (quello della sottoclasse) che dipende dal tipo effettivo

Ricordiamo che l’analisi statica effettuata dal compilatore verifica anche le regole di scoping Anche queste vengono realizzate rispetto al tipo apparente Le regole sono quelle che abbiamo visto L’estensione ai sottotipi e’ banale Visibilita’ dei nomi e regole di scoping

Da una classe sono direttamente visibili nell’ordine i propri nomi statici e quelli delle superclassi I metodi statici hanno la visibilita’ della classe di appartenenza (quella in cui sono dichiarati) oltre ai nomi locali Non vediamo i nomi d’istanza, infatti non ci sono oggetti di riferimento Variabili + metodi statici

Da un oggetto sono direttamente visibili nell’ordine i propri nomi d’istanza (inclusi quelli ereditati) e la classe, tramite questa le variabili statiche sue e delle superclassi I metodi d’istanza (inclusi i costruttori) hanno la visibilita’ dell’oggetto su cui sono eseguiti Infatti le variabili d’istanza appartengono agli oggetti, e le variabili statiche sono condivise tra tutti gli oggetti della classe Variabili + metodi d’istanza