- Делегати - Delegates
В безкрайните усилия VB да използва указатели, Microsoft разви възможността да се извикват
делегати, което съдейки по документацията, обезпечава алтернатива на функционалните указатели.
Променливата
указател (pointer variable или pointer) е променлива, чиято стойност е
адрес от паметта. Адресът, към който сочи указателя е целта (target) на указателя, затова казваме, че Променливата указател сочи към целеви адрес. Ако целевият
адрес е данна от тип Integer, казваме,че указателят е от тип Integer или Integer указател. Типът на указателя е типът на
целевата променлива. (видяхме, че референтните типове, променливи от тип Object и String са указатели; т.e., техните стойности сочат адреса на
данните в паметта.)
Указателят може да сочи и към функция, това означава, че съдържа адреса
на функция. В този случай, имаме указател на функция (function pointer). Една област в която се използват указатели на функция е в контекста на функции за обратно повикване (callback functions). Ако искаме
да преброим всички шрифтове в дадена
система, Windows API доставя
функция, наречена EnumFontFamiliesEx:
Public Declare Function EnumFontFamiliesEx
Lib "gdi32" Alias "EnumFontFamiliesExA" ( ByVal hdc As
Long, lpLogFont As LOGFONT, ByVal lpEnumFontProc As Long, ByVal lParam As Long,
ByVal dw As Long) As Long
Третият параметър изисква адреса на функцията, която трябва
да декларираме, наречена callback function. Основание за този термин имаме,
защото Windows иска да извика нашата функция за всеки шрифт в системата, подавайки информация за шрифта в
параметрите на функцията. Функция за обратно повикване (callback function):
Public Function EnumFontFamExProc(ByVal lpelfe As Long, ByVal
lpntme As Long, ByVal FontType As Long, ByRef lParam As Long) As Long
В случая за да използваме EnumFontFamiliesEx, се нуждаем от подаване на адреса
на функцията, като един от параметрите.
Това е направено във VB чрез оператор AddressOf.
Оператор AddressOf е изпълнен във VB 6 да изрази намерението да се подаде адреса на функцията на API функциите.
Във VB .NET, оператор AddressOf връща делегат (delegate):
Делегагът е Унитарен оператор, който създава процедура делегат на инстанция, референтна на специална
процедура. Нека да
дискутираме делегатите. Дефиниция: делегат (delegate) e обект на клас произхождащ от предишен Delegate class или MulticastDelegate class. Тези два класа са абстрактни, така че не могат да се създадат
обекти от тях. Въпреки това от тези класове могат да произлизат други класове и
могат да се създават обекти от тези произхождащи класове. Във VB .NET, делегати могат да се използват за да
викат методи на обекти или да поддържат функции за обратно повикване. В добавка,
VB .NET използва делегати за да свърже събитията с техните манипулатори (handlers). VB .NET поддържа също
инструменти (като метод AddHandler) за
автоматизация на този процес, така че няма нужда да използваме делегати за тази
цел.
Обектът делегат наследява редица свойства и
методи от Delegate или MulticastDelegate класове. Обектът делегат (delegate object) има:
· Свойство Target което свързва обекта или обектите, чиито метод или методи ще
се викат.
· Свойство Method което връща обект MethodInfo , описващ метод или методи
асоциирани с делегата.
· Метод Invoke който вика целевия метод или методи.
Има два класа делегати, защото делегати произлизащи от клас Delegate могат да викат само отделен метод, докато делегати произлизащи от клас MulticastDelegate могат да викат много методи.
Простите делегати
(Simple Delegates) пазят списък от указатели към една функция и викат
само един метод. Важно е за сигнатурата (function definition) да
съвпада с тази на виканата функция.
Мултикастинг делегатите (Multicast Delegates) пазят
списък от указатели към няколко функции и важно за
тях е, че интерфейсите на всички методи, които се викат от делегата трябва да
са същите. Понякога интерфейсите на тези методи са референтни на сигнатурата (signature)
на делегата. Всички сигнатури на делегати и функции трябва да съвпадат
коректно.
· Използване на делегат за викане на метод
За илюстрация си представете клас модул с метод:
Public Class Class1
Public Sub AMethod(ByVal s
As String)
Msgbox(s)
End Sub
End Class
Сега в модула Windows Form, декларираме (single cast) делегат с някои параметри като
целевия метод, който искаме да извикаме:
Delegate Sub
ADelegate(ByVal s As String)
Делегатът използва следния код да извика AMethod на Class1:
Protected Sub
Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles
MyBase.Click
' обект от тип Class1
Dim obj As New Class1( )
' деклариране на нов делегат - delegate
Dim delg As ADelegate
' дефиниране на delegate, подаване на адреса на
обектния метод
delg = New ADelegate(AddressOf
obj.AMethod)
' сега да извикаме метод, използвайки Invoke method
на делегата
delg.Invoke("testmethod")
End Sub
В документацията конструкторана делегати (delegate class constructor)
има два параметъра:
delg = New
ADelegate(TargetObject, PointerToMethodOfObject)
Но Visual Basic не може да обработи втория параметър, затова VB поддържа
специален синтаксис:
delg = New
ADelegate(AddressOf obj.AMethod)