On 04/dic/07, at 12:06, Gilberto De Faveri wrote:
On 04/dic/07, at 11:41, Massimo Valle wrote:
Questo è vero per una subclass, che la rende di fatto un oggetto
non facilmente riutilizzabile.
Ma con i delegates si potrebbe sostanzialmente agganciare l'evento
Action a qualsiasi metodo, sia esso globale o un metodo di un
oggetto istanziato. Ottenendo lo stesso controllo fine che si
ottiene istanziando un oggetto da IDE. Per inciso il metodo dei
delegates è ampiamente utilizzato in Cocoa, ma anche in altri
linguaggi.
Non ti seguo. Pur potendo utilizzare i delegati come puntatori a
funzione non sarebbe comunque possibile (nè in linea con i principi
dell'OOP a dire il vero) agganciarli "per istanza" del controllo.
In parole povere, a prescindere dalle limitazioni imposte da scelte
progettuali, non vedo il modo per specificare a runtime con i
delegati quello che permette di fare l'IDE (ad. esempio, nel caso
dell'ormai famoso PushButton, specificare un Action() diversa "per
istanza").
Puoi fare un esempio?
Ti propongo un esempio con un Timer, così nello stesso tempo creiamo
qualcosa di funzionante ed utilizzabile.
Quello che ti descrivo di seguito è un modo per creare una subclass
di Timer riutilizzabile che possa venire istanziata al runtime e il
cui evento Action() possa essere agganciato ad un metodo diverso per
ogni istanza.
1. Partendo da un nuovo progetto, prima di tutto creiamo un nuovo
Modulo che ci serve per specificare il nostro delegate. Chiamiamo il
modulo "Delegates" per semplicità.
2. Nel modulo Delegates definiamo un nuovo delegate così:
Delegate Sub TimerAction()
3. Ora definiamo una sottoclasse di Timer che chiameremo
"DelegatingTimer"
4. Nel DelegatingTimer definiamo una proprietà:
DelegateMethod as TimerAction
5. Nel DelegatingTimer creiamo un metodo costruttore:
Sub Constructor(MethodToCall as TimerAction)
DelegatedMethod = MethodToCall
End Sub
6. Nell' evento Action() di DelegatingTimer inseriamo:
Sub Action()
DelegateMethod.invoke
End Sub
Ora il nostro timer con delegate è terminato. Proviamo ad utilizzarlo.
1. Nella finestra Window1 (già presente in un nuovo progetto) creiamo
una proprietà:
WindowTimer as DelegatingTimer
2. Sempre nella nostra finestra creiamo un metodo che si conforme
alla specifica del nostro delegate. Una semplice Sub senza argomenti:
Sub TimerDelegate()
msgBox "Tempo scaduto"
End Sub
3. Inseriamo un pushButton nella finestra, o qualunque altro modo per
istanziare il nostro Timer con questo codice:
WindowTimer = new DelegatingTimer(addressOf self.TimerDelegate)
WindowTimer.mode = 0
WindowTimer.enabled = true
WindowTimer.period = 3000
WindowTimer.mode = 1
WindowTimer.reset
Ecco fatto.
Premendo il pulsante (o invocando il metodo) che esegue il codice al
punto 3 creiamo un'istanza del nostro Timer a cui assegniamo
un'azione che decidiamo noi. In questo caso, quando il timer scade
gli facciamo eseguire il metodo TimerDelegate della finestra, ma
avremmo potuto specificare un qualsiasi altro metodo purchè conforme
alla dichiarazione del delegate.
Nello stesso modo possiamo istanziare il nostro timer altre volte,
assegnando ogni volta un'azione diversa a seconda del caso. E nello
stesso progetto possiamo riutilizzare più volte lo stesso
DelegatingTimer in altre parti per fare ciò che vogliamo.
Massimo
|