ActionScript: _parent e controllo dei contesti
Mercoledì 22 Agosto, 2007Quando "scatta" un evento di un oggetto il contesto, ovvero l'oggetto madre che rappresenta l'area di validità di tutte le variabili, diventa l'oggetto stesso. Questa caratteristica, propria della programmazioni Object Oriented, può disorientare provocando errori e malfunzionamenti nel codice. Inoltre, in determinate situazioni, può impedire di accedere ad alcune variabili "prima" disponibili.
Prima di tutto vediamo una caratteristica di ActionScript legata alla gestione dei contesti che, se compresa, ci farà risparmiare alcune ore di inutili prove. Quando abbiamo a che fare con oggetti grafici o più semplicemente di MovieClip innestati uno all'interno dell'altro, la proprietà _parent risolve qualsiasi problema di contesto. Ad esempio se il MovieClip padre_mc contiente un altro MovieClip figlio_mc e si usa il seguente codice:
-
// codice all'interno di padre_mc
-
figlio_mc.onRelease = function() {
-
trace(this); // figlio_mc
-
trace(this._parent); // padre_mc
-
}
Risalisre al "padre", quindi, risulta chiaro ed immediato.
Con classi pure, di solo codice, o estensioni di MovieClip, la proprietà _parent non è disponibile e le cose si potrebbero complicare! Immaginiiamo di avere una Classe MyClass:
-
Class MyClass extends MovieClip {
-
function MyClass() {
-
// constructor
-
}
-
//
-
function myMethod() {
-
trace(this); // myClass
-
var num = 5;
-
var cp = this;
-
....
-
var myObject = new [ un oggetto ];
-
myObject.onLoad = function() {
-
trace(this); // myObject
-
trace(cp); // myClass
-
}
-
}
Il contesto di MyMethod() è, ovviamente, this, ovvero il puntatore alla classe MyClass. La variabile num, ad esempio, ha un ciclo di vita racchiuso all'interno del metodo MyMethod(). È visibile quindi solo all'interno del metodo e verrà distrutta all'uscita. Stessa cosa per la variabile myObject che tuttavia inizializza un evento, in questo caso onLoad. Quando scatterà onLoad() il contesto diventerà myObject lasciandoci, apparentemente, senza il puntatore alla classe madre myClass. Analizzando attentamente il codice ci accorgiamo che la variabile cp, definita nel metodo myMethod(), ha lo stesso contesto della variabile myObject! Infatti la variabile cp (class pointer) sarà visibile all'interno del metodo onLoad dell'oggetto myObject in quanto condivide con esso lo stesso contesto. In realtà il metodo myMethod() non viene deallocato proprio perchè l'oggetto myObject ha necessità di "vivere" più al lungo del previsto visto che ha "allocato" un evento (di tutto questo se ne occupa Flash a nostra "insaputa").
Consiglio
Per gli eventi legati a bottoni o a MovieClip una buona abitudine sarebbe quella di usare la forma:
-
my_mc.onRelease = myOnRelease;
-
function myOnRelease() {
-
trace(this); // _root
-
trace("Click me");
-
}
Al posto della più rapida ed immediata:
-
my_mc.onRelease = function() {
-
trace(this); // my_mc
-
trace("Click me");
-
}
Il vantaggio di usare un funzione esterna è quella di avere un contesto neutro e la possibilità di accedere alla funzione a prescindere dal MovieClip che la controlla. Nel secondo caso, ad esempio, se volessi forzare l'esecuzione del codice legato al "click" del MovieClip dovrei usare un codice di questo tipo:
-
my_mc.onRelease();
In pratica chiamo l'evento come fosse un metodo. Tuttavia devo - appunto - avere a disposizione il MovieClip my_mc. Nell'altro modo, invece, posso eseguire il codice chiamando direttamente myOnRelease(). Ovviamente, come mostrato negli esempi, occhio ai contesti. Nel primo caso il contesto di myOnRelease() è quello dell'oggetto madre dove è scritto, ad esempio _root. Nel secondo caso, invece, il contesto è sempre il MovieClip my_mc!
Forzare un diverso contesto
Concludiamo con un tricks utile in molte circostanze. Flash mette a disposizione una libreria, mx.utils, con un oggetto Delegate in grado di forzare un contesto di un metodo o funzione. Il suo uso è davvero semplice:
-
import mx.utils.Delegate;
-
//
-
var my_mc; // puntatore ad un MovieClip
-
var my_btn; // un bottone
-
function myFunction() {
-
trace(this);
-
}
-
my_btn.onPress = Delegate.create(my_mc, myFunction);
L'evento onPress del bottone my_btn punta ad un "nuova" funzione creata appunto con il contesto my_mc. Quando si clicca sul bottone my_btn, il codice eseguito in myFunction() avrà come contesto my_mc!






















Lascia un commento