A2 & Oberon GOOGLE trans to English      Помощь      Поиск      Пользователи  Файловый архив


 Страниц (2): [1] 2 »   

> Описание: вопросы новичков
lit-uriy Супермодератор
Отправлено: 04 Января, 2009 - 06:30:09
Post Id


Advanced Member


Покинул форум
Сообщений всего: 298
Дата рег-ции: Нояб. 2008  
Откуда: Тюмень / Новосибирск
Репутация: 0




с чем едят эти самые делигаты?
Приер из модуля WMComponents.Mod:
PointerHandler*  = PROCEDURE {DELEGATE} (x, y : LONGINT; keys : SET; VAR handled : BOOLEAN);


Что собственно эта запись означает? (числится в типах)
 
 Top
Wlad
Отправлено: 04 Января, 2009 - 12:13:02
Post Id


Newbie


Покинул форум
Сообщений всего: 32
Дата рег-ции: Окт. 2008  
Откуда: Харьков. Украина
Репутация: 0




lit-uriy пишет:
с чем едят эти самые делигаты?
Приер из модуля WMComponents.Mod:
PointerHandler*  = PROCEDURE {DELEGATE} (x, y : LONGINT; keys : SET; VAR handled : BOOLEAN);


Что собственно эта запись означает? (числится в типах)

Да примерно то же самое, что и тип делегата в Си-шарпе.
То есть вы можете объявить в любом месте переменную типа этого делегата и присваивать ей ссылку на любой метод любого экземпляра любого класса, если сигнатура этого метода совпадает с описанием типа данного делегата.
Но, в отличие от Си-шарпа, можно и просто присвоить ссылку на процедуру модуля (то есть, не описанную в объекте).

(Отредактировано автором: 04 Января, 2009 - 12:24:25)

-----
У России только два союзника: её Армия и Флот.

 
 Top
BohdanT Администратор
Отправлено: 04 Января, 2009 - 12:22:34
Post Id



Super Member


Покинул форум
Сообщений всего: 606
Дата рег-ции: Июль 2008  
Откуда: Киев, Украина
Репутация: 2




Делегат (англ. delegates) — типобезопасный указатель на функцию.
Делегаты введены для определения прототипа функции обратного вызова.



TYPE
(** Installable event preview handlers. Are called by the components sequencer thread *)
PointerHandler* = PROCEDURE {DELEGATE} (x, y : LONGINT; keys : SET; VAR handled : BOOLEAN);
.....
VisualComponent* = OBJECT(Component)
VAR
(*Обявляем переменные*)
extPointerDown, extPointerUp, extPointerMove : PointerHandler;
.....
(*Устанавливаем*)
PROCEDURE SetExtPointerMoveHandler*(handler : PointerHandler);
BEGIN
Acquire; extPointerMove := handler; Release
END SetExtPointerMoveHandler;
.....
(*Работаем с делегатом*)
IF extPointerMove # NIL THEN extPointerMove(msg.x, msg.y, msg.flags, handled) END;

.....
(*Устанавливаем обработчик в своем компоненте*)
selectedObj.SetExtPointerMoveHandler(HandlePointerMove);


(Добавление)
{DELEGATE}
Делегаты подобны процедурным типам; они совместимы как с процедурами так и с методами, в то время как процедурные типы совместимы только с процедурами.

Делегаты процедурных типов помечаются модификатором DELEGATE. Делегатам могут быть назначены процедуры и методы. Пусть даны переменная с процедурным типом t, экземпляр объекта o и метод M связанный с o, тогда можно записать o.M в t, если конечно метод и t обладают совместимыми сигнатурами. Ссылка на сам объект исключается из сигнатуры процедурного типа. Всякий раз при вызове t назначенный объект o явно передается в self-ссылку (self-reference). Присваивания и вызовы процедур остаются совместимыми с описанием Oberon.
Нетрассируемые указатели — это указатели, которые не отслеживаются сборщиком мусора. Структура или объект, на которые ссылаются только нетрассируемые указатели, могут быть в любой момент утилизированы сборщиком мусора.
 
 Top
Wlad
Отправлено: 04 Января, 2009 - 13:43:50
Post Id


Newbie


Покинул форум
Сообщений всего: 32
Дата рег-ции: Окт. 2008  
Откуда: Харьков. Украина
Репутация: 0




BohdanT пишет:
Нетрассируемые указатели — это указатели, которые не отслеживаются сборщиком мусора. Структура или объект, на которые ссылаются только нетрассируемые указатели, могут быть в любой момент утилизированы сборщиком мусора.

Вот, кстати, Богдан, эти две фразы мне много раз попадались в сети на счёт АО(А2) нетрассируемых указателей...
Тут ошибочки нет случаем? Противречия? В смысле забирания в любой момент сборщиком мусора... Ежели они им не отслеживаются...
Взять в сравнение КП, так там именно для этого нетрассируемость указателя и объявляется: 1) мы сами следим за указателем 2) что бы система сборки мусора НЕ трогала наши указатели... 3) для совместимости с системой исполнения подлежащей ОСи - у нас ведь указатель уже может исчезнуть из "поля зрения", а в недрах ОСи (куда мы его, например, в виде аргумента функции) передали, он ещё действителен...
Или в связи с тем, что в случае А2 "подлежащей системы", чуждой А2 нет, дисциплина меняется?
Тогда совсем не понятно - что это за указатели, которые у нас в любой момент могут "из рук выхватить"? Улыбка

-----
У России только два союзника: её Армия и Флот.
 
 Top
lit-uriy Супермодератор
Отправлено: 04 Января, 2009 - 14:01:09
Post Id


Advanced Member


Покинул форум
Сообщений всего: 298
Дата рег-ции: Нояб. 2008  
Откуда: Тюмень / Новосибирск
Репутация: 0




Wlad
Wlad пишет:
Тут ошибочки нет случаем? Противречия?
у меня к стати тоже сомнения, надо в оригинал глянуть. а то не логично как-то
(Добавление)
Wlad пишет:
Да примерно то же самое, что и тип делегата в Си-шарпе.
Я о существовании С# лишь слышал
(Добавление)
Все равно небельмеса не понял.
Вот есть в С/С++ указатели на функции, А в борландовском паскале подобное нзывалось процедурный тип, который вроде в Обероне отсутствует.

Дак вот это тоже самое или нет?
(Добавление)
разглядывал я такой пример:

TYPE
MediaPlayer = OBJECT
PROCEDURE Start; .... play a movie .... END Start;
PROCEDURE Stop; .... stop movie .... END Stop;
END MediaPlayer;

ClickProc = PROCEDURE {DELEGATE} (button: Button);
Button = OBJECT
VAR
onClick: ClickProc;
caption: ARRAY 32 OF CHAR;

PROCEDURE OnClick;
BEGIN onClick(SELF) END OnClick;

PROCEDURE & Init(caption: ARRAY OF CHAR; onClick: ClickProc);
BEGIN SELF.onClick := onClick; COPY(caption, SELF.caption)
END Init;
END Button;

PROCEDURE Init(p: MediaPlayer);
VAR b0, b1, b2: Button;
BEGIN
(* Reboot -> call system reboot function *)
NEW(b0, "Reboot", System.Reboot);

(* MediaPlayer UI: bind buttons with player instance *)
NEW(b1, "Play", p.Play);
NEW(b2, "Stop", p.Stop);
END Init;

(Добавление)
взятый тут
во-первых, я думаю есть опечатка в 28 строке (p.Play вместо p.Start);
во-вторых, указатель на процедуру (собственно делегатом помечен) имеет такую сигнатуру:
(button: Button)

а в строке 28 и 29 в конструктор кнопки передается метод p.Stop, имеющий такую сигнатуру:
__
т.е. ничего, а поидее должны быть одинаковы

П.С. мозг уже почти выкипел, спасайте.
 
 Top
Wlad
Отправлено: 04 Января, 2009 - 15:25:04
Post Id


Newbie


Покинул форум
Сообщений всего: 32
Дата рег-ции: Окт. 2008  
Откуда: Харьков. Украина
Репутация: 0




lit-uriy пишет:
Дак вот это тоже самое или нет?.

Ну, вопсчем, считайте, что - ДА. Улыбка
Единственно, с ассоциацией с Си++ - поосторожней. Там указатели на методы, скорее НЕ указатели, а ... индексы... Если от этого вам полегчает... Улыбка

В приведённом примере - да - есть ошибки. С названием вызываемого метода и с сигнатурами ссылаемых методов. Описание делегата не должно содержать аргументов типа кнопки.

Для себя примите, что указатель на метод (делегат) - не просто указатель, а - некий объект из пары указателей. Один из указателей - ссылка на метод, а второй - указатель на экземпляр объекта, в описании класса которого описан этот метод. Просто в случае указателей на процедуру-НЕ метод (описанную в модуле и вне всех объектов), указатель на экземпляр содержит NIL (на самом деле это не всегда и не совсем так, но сейчас Вам лучше не заморачиваться Улыбка )...

-----
У России только два союзника: её Армия и Флот.
 
 Top
MaDzi
Отправлено: 04 Января, 2009 - 15:29:53
Post Id



Member


Покинул форум
Сообщений всего: 102
Дата рег-ции: Дек. 2008  
Откуда: Саратов
Репутация: 0




lit-uriy пишет:
П.С. мозг уже почти выкипел, спасайте.


Давайте разбираться. Только предлагаю взять не сомнительный код, который не проверялся на системе, а вполне конкретный модуль из поставки.


MODULE GenericSort; (** AUTHOR "Luc Blaeser"; PURPOSE "Generic Sort Functionality" *)
(** Модуль занимается сортировкой всего и вся *)

TYPE
GenericArray* = POINTER TO ARRAY OF ANY;
(** Определяется массив указателей на что-либо *)
GenericCompareFunct* = PROCEDURE {DELEGATE} (obj1, obj2: ANY): BOOLEAN;
(** Вот он делегат, процедура которая производит сравнение двух объектов *)
(** Функция должна вернуть TRUE только когда obj1 < obj2 *)

(** Процедура реализующая быструю сортировку, принимает в качестве параметров массив указателей и процедуру сравнения (делегат) *)
PROCEDURE QuickSort*(VAR genArray: GenericArray; compFunc: GenericCompareFunct);
BEGIN
QuickSortRec(genArray, compFunc, 0, LEN(genArray)-1)
END QuickSort;

(** Процедура непосредственно реализующая сортировку *)
PROCEDURE QuickSortRec(VAR genArray: GenericArray; comp: GenericCompareFunct; lo, hi: LONGINT);
VAR i, j: LONGINT; x, t: ANY;
BEGIN
i := lo; j := hi;
x := genArray[(lo+hi) DIV 2];

WHILE (i <= j) DO
(** Собственно вызовы делегатов *)
WHILE (comp(genArray[i], x)) DO INC(i) END;
WHILE (comp(x, genArray[j])) DO DEC(j) END;
IF (i <= j) THEN
t := genArray[i]; genArray[i] := genArray[j]; genArray[j] := t;
INC(i); DEC(j)
END
END;

IF (lo < j) THEN QuickSortRec(genArray, comp, lo, j) END;
IF (i < hi) THEN QuickSortRec(genArray, comp, i, hi) END
END QuickSortRec;

END GenericSort.

(Добавление)
Модуль WebStd.Mod, где используется сортировка

Далее объект, который реализует делегатную функцию:

PersistentDataSorter = OBJECT
VAR
comp: PersistentDataCompare;

PROCEDURE &Init*(persComp: PersistentDataCompare);
BEGIN (* persComp # NIL *)
comp := persComp
END Init;

PROCEDURE GenericCompare(obj1, obj2: ANY): BOOLEAN;
VAR persO1, persO2: PersistentDataObject;
BEGIN
persO1 := obj1(PersistentDataObject); persO2 := obj2(PersistentDataObject);
RETURN comp(persO1, persO2)
END GenericCompare;
END PersistentDataSorter;

Обратите внимание, процедура полностью совпадает по сигнатуре.

И непосредственно применение делегата

PROCEDURE GetElementList*(filter: PersistentDataFilter; persComp: PersistentDataCompare) : PersistentDataObjectList;
VAR i: LONGINT; filteredList: TFClasses.List; persList: PersistentDataObjectList; p: ANY; obj: PersistentDataObject;
genArray: GenericSort.GenericArray; persSorter: PersistentDataSorter;
BEGIN
NEW (filteredList);
IF (filter = NIL) THEN filter := DefaultPersistentDataFilter END;
dataObjList.Lock;
FOR i := 0 TO dataObjList.GetCount()-1 DO
p := dataObjList.GetItem(i); obj := p(PersistentDataObject); (* obj # NIL & obj.oid # 0 since it was registered in prevalence system*)
IF (filter(obj)) THEN
filteredList.Add(obj)
END
END;
dataObjList.Unlock;
IF (filteredList.GetCount() > 0) THEN
NEW(genArray, filteredList.GetCount());
FOR i := 0 TO filteredList.GetCount()-1 DO
genArray[i] := filteredList.GetItem(i)
END;
IF (persComp # NIL) THEN
NEW(persSorter, persComp);
GenericSort.QuickSort(genArray, persSorter.GenericCompare)
END;
NEW(persList, LEN(genArray));
FOR i := 0 TO LEN(genArray)-1 DO
persList[i] := genArray[i](PersistentDataObject)
END;
RETURN persList
ELSE
RETURN NIL
END
END GetElementList;
 
 Top
BohdanT Администратор
Отправлено: 04 Января, 2009 - 15:51:56
Post Id



Super Member


Покинул форум
Сообщений всего: 606
Дата рег-ции: Июль 2008  
Откуда: Киев, Украина
Репутация: 2




что т я не ппойму, а в чем вопрос собственно?
 
 Top
lit-uriy Супермодератор
Отправлено: 04 Января, 2009 - 16:26:04
Post Id


Advanced Member


Покинул форум
Сообщений всего: 298
Дата рег-ции: Нояб. 2008  
Откуда: Тюмень / Новосибирск
Репутация: 0




так
1) пример значит кривой в оф.доке Не понял
2) делегат - универсальный указатель на процедуру модуля/типа
(в С++ нельзя создать указатель на функцию-член любого класса, только данного конкретного. Поэтому есть довольно много реализаций делегатов, типа кто круче напишет)
3) сигнатуры должны железно совпадать.

Ну тогда можно спать спокойно. Спасибо всем за помощь.
(Добавление)
ага вот еще вопрос применительно к Активному Оберону. А через делегат вызов осуществляется немедленно, т.е. как вслучае прямого вызова процедуры. Или это может откладыватся в некоторых случаях (многопоточная работа)?
 
 Top
BohdanT Администратор
Отправлено: 04 Января, 2009 - 16:51:12
Post Id



Super Member


Покинул форум
Сообщений всего: 606
Дата рег-ции: Июль 2008  
Откуда: Киев, Украина
Репутация: 2




lit-uriy пишет:
ага вот еще вопрос применительно к Активному Оберону. А через делегат вызов осуществляется немедленно, т.е. как вслучае прямого вызова процедуры. Или это может откладыватся в некоторых случаях (многопоточная работа)?

Всегда можно глянуть сгенерированный код Подмигивание
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 1 (гостей: 1, зарегистрированных: 0, скрытых: 0)
« ActiveOberon »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Locations of visitors to this page
[Valid RSS]

RSS

Valid CSS!


Powered by ExBB
ExBB FM 1.0 RC1 by TvoyWeb.ru
InvisionExBB Style converted by Markus®

[Script Execution time: 0.0154]     [ Gzipped ]