Home > doc > object-model 
 en fr de es nl pl pt pt_BR mk sq ca hu cs tr ar fa id vi ko ja ru zh zh_TW eo
Precedente  Successivo  Modifica  Rinomina  Undo  Refresh  Search  Amministrazione  
Documentazione
History
 
Attenzione! Questa pagina non è aggiornata.  Vedi versione in inglese 
Il modello a oggetti

1. Oggetti e classi

Un' oggetto (object) in Gambas è una struttura di dati atta a contenere proprietà (properties), variabili (variables), metodi (methods) ed eventi (events).

Gli oggetti sono accessibili per riferimento (by reference), per esempio, è possibile usare un puntatore su di essi, per ottenere una variabile (variabile), la quale contiene l'indirizzo in memoria della struttura dell'oggetto stesso.

E' possibile conoscere stampandolo, l'indirizzo di un'oggetto (object) usando l'istruzione PRINT.

DIM aStr AS NEW String[]

PRINT aStr

(String[] 0x80dccf8)

La struttura dei dati di un'oggetto (object) è definita da una classe (classe).

1.1. Classi

Ogni oggetto Gambas ha una classe che lo descrive in tutte le sue proprietà pubbliche, i suoi metodi e i suoi eventi. La classe è lo stampo con cui si creano gli oggetti, ed è fondamentale in Gambas. Esse sono il pilastro su cui Gambas si erge.

Una classe può essere statica in questo caso tutti i suoi membri sono statici (vedi oltre). In Gambas, una classe statica, è chiamata anche modulo.

Una classe statica non può essere istanziata, si creerebbe una variabile che fa riferimento ad un'oggetto già dichiarato il che non ha alcun senso. Gambas per facilitare la vita al programmatore, include all'avvio dell'interprete classi che non sono facenti parte strettamente del linguaggio stesso (il basic) ma, essendo di uso molto comune, le carica come predefinite. Questo fa sembrare appunto una classe statica come facente parte del linguaggio ma non è così. Questa facilitazione è in contrapposizione con altri linguaggi in cui qualsiasi classe non facente parte del linguaggio deve essere necessariamente istanziata prima del suo utilizzo.

Esempio

La classe System è una classe statica, tutti i suoi metodi sono di conseguenza anch'essi statici, non è possibile quindi creare un oggetto da System. Viceversa in qualsiasi punto del programma la si vorrà utilizzare essa sarà disponibile un pò come fosse un modulo.

Una virtual class è una pseudo-classe nascosta che non è possibile manipolare esplicitamente.

1.2. Properietà, metodi e variabili

Le proprietà e i metodi, permettono di manipolare i dati contenuti all'interno nella struttura della classe.

Una proprietà, un metodo o una variabile, possono essere statici:

Un metodo o una variabile possono essere o pubblici o privati, mentre una proprietà, e SEMPRE pubblica.

Quando si dichiara un simbolo come private esso può essere usato solo all'interno della classe stessa dove è dichiarato. Viceversa un simbolo dichiarato public può essere utilizzato ovunque, purché si disponga ovviamente di un riferimento che punta all'oggetto in questione.

1.3. Riferimenti

I riferimenti, sono indirizzi di memoria dove l'oggetto comprensivo dei suoi dati, viene allocato. Quindi ad ogni istanza di un'oggetto viene occupata una distinta locazione di memoria. Questo porta a consumare più memoria rispetto alla tradizionale programmazione procedurale, ed è per questo che i moderni linguaggi orientati agli oggetti dispongono di un meccanismo automatico più o meno sofisticato per liberare la memoria non più utilizzata. Questo meccanismo si chiama GC che sta a garbage collector (tradotto significa colui che raccoglie la spazzatura). Gambas non implementa un vero e proprio GC come in Java ma più semplicemente un'oggetto contatore di riferimenti e più precisamente:

Ogni volta che si istanzia un'oggetto esso (il GC) viene incrementato ed ogni volta che esso viene rilasciato viene decrementato. Quando questo contatore torna a zero vuol dire che non c'è più nessuna variabile che punta ad esso. A questo punto, si ritiene che l'oggetto non sia più utilizzato e la memoria viene liberata.

1.4. Oggetti non validi

Un'oggetto può essere definito come non valido (invalid). Questo per esempio, quando si cerca di fare riferimento ad un'oggetto che è stato distrutto di cui è rimasto il link (un orfano) che Gambas non ha potuto gestire.

Cercando di utilizzare un'oggetto non valido (object) si solleva un errore.

1.5. Metodi speciali

I metodi speciali, sono metodi nascosti il cui nome comincia con un carattere di sottolineatura, essi sono chiamati dall'interprete nelle seguenti situazioni:

Fare riferimento a Metodi speciali e /api/cat/special per ulteriori informazioni.

2. Eventi e osservatori

2.1. Eventi

Gli eventi, sono segnali trasmessi da un'oggetto quando succede qualcosa al suo interno.

Se un'oggetto solleva un'evento, vi sarà un riferimento all'osservatore o al suo oggetto padre.

L' osservatore è anch'esso un'oggetto che implementa l'aggancio agli eventi, esso è in definitiva un metodo pubblico, che viene chiamato ogni volta che viene sollevato un'evento.

Per impostazione predefinita, l'osservatore è l'attuale oggetto in cui viene dichiarato il neo oggetto istanziato.

Per essere sollevato, un evento di un'oggetto esso deve avere un nome. Questo nome di evento viene assegnato all'oggetto durante al sua creazione con l'istruzione NEW tramite la parola chiave AS questo nome sarà come prefisso per tutti i collegamenti agli eventi di quell'oggetto.

Esempio

Questo esempio, crea un controllo bottone (Button) che potrà lanciare eventi.

DIM hBottone AS Button

hBottone = NEW Button(ME) AS "BottoneEventoNome"

Se nessun nome viene specificato con la parola chiave AS, allora l'oggetto non potrà lanciare alcun evento!.

2.2. Blocco degli oggetti

Un'oggetto, può essere bloccato in modo da impedire la capacità di sollevare eventi, e può successivamente essere sbloccato per consentire di nuovo il loro sollevamento. Il poter bloccare gli eventi è utile in fase di inizializzazione di un'oggetto, quando per esempio l'impostazione di proprietà, potrebbe sollevare degli eventi destinati a impostare proprietà che in quel momento non sono ancora state definite o peggio che fanno riferimento a se stessa chiamandosi ricorsivamente fino al raggiungimento della fine dello stack mandando in crash l'applicativo. Per ulteriori informazioni, fare riferimento a Object.Lock e Object.Unlock metodi. Alcuni eventi possono essere cancellati dal gestore usando l'istruzione STOP EVENT, l'effetto di questa cancellazione dipende dal tipo di evento.

Attenzione! un'oggetto viene automaticamente bloccato durante l'esecuzione del suo costruttore, esso è quindi impossibilitato per quanto detto sopra a sollevare o ricevere eventi.

2.3. Osservatori

Gli osservatori (Observers) sono oggetti che permettono d'intercettare eventi lanciati da altri oggetti che sono "osservati" appunto. E' possibile intercettare eventi prima che siano lanciati o subito dopo che lo sono stati. Per ogni evento intercettato, l'osservatore sollevarà un'evento che avrà lo stesso nome e lo stesso argomento. Usando l'istruzione STOP EVENT all'interno di un' osservatore di eventi l' evento stesso originale verrà cancellato.

Esempio

PRIVATE $hBottone as Button
PRIVATE $hOsservatore AS Observer

PUBLIC SUB Form_Load()
  $hBottone = NEW Button(ME) AS "Bottone"
  $hOsservatore = NEW Observer(hBottone) AS "MioOsservatore"
END

PUBLIC SUB MioOsservatore_Click()
  DEBUG "Il bottone è stato premuto e l'evento cancellato!"
  STOP EVENT
END

PUBLIC SUB Bottone_Click()
  DEBUG "Questo testo non sarà mai visibile."
END

3. Ereditarietà

3.1. Che cosa è l'ereditarietà?

L'ereditarietà è la capacità di poter specializzare una classe partendo da una classe padre, ereditando tutti i metodi,le proprietà e gli eventi. Così che non si debba duplicare del codice già pronto e funzionante per poter costruire una classe che abbia molte similitudini, ma che al contempo aggiunga nuove funzionalità.

Attenzione! E' necessario usare la parola chiave ME per accedere agli elementi ereditati dall'interno della classe.

3.2. Quale classe può essere una classe padre?

È possibile ereditare da qualsiasi classe, anche da una nativa! Non è stupendo?

Per esempio, è possibile creare una MiaListBox personalizzata ereditando dalla classe ListBox, e aggiungervi per esempio la caratteristica di poter associare un tag (cioè qualcosa di estremamente vario da poter utilizzare in molti modi) uno per ogni elemento della lista.

Notare che non è possibile usare INHERITS in un file di classe FORM, questo perché esso già eredita dalla classe Form.

Attenzione! La profondità con cui è possibile creare nuovi oggetti ereditandoli, non può superare i 16 livelli. Questo è il limite che l'interprete di Gambas pone.

3.3. Dispacciamento virtuale

Quando un metodo viene chiamato, o si accede a una proprietà tramite un riferimento ad un'oggetto, Gambas permette di usare il dispacciamento virtuale (../../def/virtual dispatching). Questo significa che vengono usati i dati direttamente della classe è non quelli della variabile che si riferisce all'oggetto, (come accadeva in Gambas 1.0).

3.4. Ereditarietà e costruttori

Contrariamente a tutti i linguaggi a oggetti conosciuti, ogni classe nella gerarchia dell'ereditarietà, utilizza i parametri passati al costruttore.

Supponiamo di avere la seguente struttura ereditata:

MiaListBox ---eredita da--> ListBox ---eredita da---> Control.

Così MiaListBox= avrà due parametri.

Siate precisi: il ListBox._new() sarà chiamato per primo, così che vi sarà la certezza che il controllo ListBox esista quando saremo in MiaListBox.new(). Gli argomenti devono essere specificati in ordine inverso.

Poi si crea un controllo MiaListBox in questo modo:

hMiaListBox = NEW MiaListBox("Nome", hContainer)

In Gambas 3, il meccanismo con cui vengono processati gli argomenti del costruttore è cambiato:

Per esempio, seupponiamo di avere il seguente schema di ereditarietà:

MioForm ---eredita da--> Form ---eredita da--> Window

Con il costruttore MioForm sono:

Sub _new(PrimoArgomento As String, SecondoArgomento as Integer, Optional TerzoArgomento As Integer)

Notare: Il costruttore del Form non accetta argomenti, e il costruttore di Window prende un'argomento opzionale dal genitore. La sintassi del costruttore finale sarà:

New MioForm(PrimoArgomento As String, SecondoArgomento As Integer, Optional Parent As Control, Optional TerzoArgomento As Integer)

In linea generale, l'ordine degli argomenti per un'ereditarietà a tre livelli è così composto:

3.5. Sovrascrittura Overriding

Quando un simbolo viene sovrascritto, il tipo di simbolo della classe figlia, deve essere compatibile con il tipo della classe padre.

Le regole sono:

4. Componenti

In Gambas i componenti (components), sono librerie esterne condivise scritte in C, C++ o direttamente in Gambas che aggiungono nuove funzionalità e/o classi all'interprete. Le Classi (Classes) sono gruppi omegenei di classi raggruppate da cui provengono.

4.1. Componenti interni predefiniti

L'interprete racchiude al suo interno dei componenti chiamati gb che definiscono tutte le classi predefinite del linguaggio. Questi componenti, vengono caricati in modo predefinito e possono essere quasi considerati parte del linguaggio.

4.2. Tabelle di simboli

Ogni componente possiede una classe con tabella dei simboli privata, in modo che i nomi delle classi non siano in conflitto fra loro.

4.3. Tabella globale dei simboli

Per fare in modo che i componenti possano lavorare insieme, quindi non entrando in conflitto fra loro, esiste una tabella dei simboli globale, in cui sono memorizzati tutte le classi esportate dai componenti e tutte le classi esportate dal progetto corrente.

Se c'è un conflitto di nomi in questa tabella dei simboli globale, l'ultima classe caricata sovrascrive quella precedentemente caricata con lo stesso nome, utilizzando l'ereditarietà. In altre parole, la classe prevalente sovrascritta, diventa un'estensione della prima.

Questa ultima peculiarità può essere usata per:

4.4. Tabella dei simboli di progetto

Il vostro progetto ha il proprio simbolo privato, tipo un componente (componenti), e può esportare qualsiasi delle sue classi, tramite la tabella dei simboli globale usando la parola chiave EXPORT.

Le classi del progetto sono caricate dopo tutti i componenti. Così la vostra classe esportata, può eventualmente sovrascrivere qualsiasi classe dichiarata in un componente.

Vedi anche

Object, Class