Хочется следующего: вызова некоторого метода базового класса формы (назовем
его AfterFormInit) после того, как выполнится Init всей иерархии классов
конкретного класса формы, причем порядок следования Init различных классов
этой иерархии может быть разным (у одного класса Dodefault() стоит после кода
Init, у другого - перед, у третьего - в середине)
Hапример так:
define class BaseForm as Form
procedure Init
......
endproc
procedure AfterFormInit
&& Хочется, чтобы мы сюда попали после всех инитов иерархии
EndProc
enddefine
define class Form1 as BaseForm
procedure Init
....
DoDefault()
....
EndProc
enddefine
define class Form2 as Form1
procedure Init
Dodefault()
....
endproc
enddefine
....
define class FormN as FormM....
enddefine
Делал следующим образом:
в BaseForm.Load писал:
procedure Load
BindEvent(This, "Init", This, "AfterFormInit", 1)
EndProc
Сначала обрадовался, что заработало, потом оказалось
а) Код AfterFormInit иногда не выполнялся (поведение случайное)
б) Иногда (при иерархии глубже трех) получаем Exception C00..5
Понимаю, что сам для себя подложил грабли, однако как можно эту задачу решить
более правильно и красиво при условии, что это не должно затрагивать код
дочерних классов, вся реализация должна идти в базовом классе?
С уважением, А. Королев
AK> Хочется следующего: вызова некоторого метода базового класса формы
AK> (назовем его AfterFormInit) после того, как выполнится Init всей
AK> иерархии классов конкретного класса формы, причем порядок следования
AK> Init различных классов этой иерархии может быть разным (у одного класса
AK> Dodefault() стоит после кода Init, у другого - перед, у третьего - в
AK> середине)
А это нужно _только_ для базового класса (т.е. только в одном слое
иерархии), или для произвольного?
Если только для одного - уйди от Init к своему методу CustomInit, который и
вызывай из Init-а базового класса, а после него уж пиши
This.AfterFormInit(), если не получил оттуда .F. Сам Init спрячь от
переопределения.
Думаю это самое правильное решение будет, но оно конечно затрагивает прочие
классы...
AK> Понимаю, что сам для себя подложил грабли, однако как можно эту задачу
AK> решить более правильно и красиво при условии, что это не должно
AK> затрагивать код дочерних классов, вся реализация должна идти в базовом
AK> классе?
Думаю именно так - никак не получится :( На то оно и переопределение
методов, чтобы можно было управлять порядком вызова кода родительских
классов... Может всё-же в описании классов указать, что RETURN DODEFAULT()
должно быть самой последней командой в переопределяемом Init-е... Хотя по
мне - это сильно неудобно. Как правило нужно наоборот - сначала код
родительского класса, и только потом - свой...
Может можно уйти от Init к Activate? С флажком блокирующем повторное
исполнение...
--
WBR, Igor
Отправлено через сервер Форумы@mail.ru - http://talk.mail.ru
AK>> Хочется следующего: вызова некоторого метода базового класса формы
AK>> (назовем его AfterFormInit) после того, как выполнится Init всей
AK>> иерархии классов конкретного класса формы, причем порядок следования
AK>> Init различных классов этой иерархии может быть разным (у одного класса
AK>> Dodefault() стоит после кода Init, у другого - перед, у третьего - в
AK>> середине)
IK> А это нужно _только_ для базового класса (т.е. только в одном слое
IK> иерархии), или для произвольного?
Любой произвольный класс должен вести себя таким образом: после _полной_
отработки кода в методе Init вызывать метод AfterFormInit, который
предназначен для окончательного этапа инициализации контролов посредством
вызова соответствующих методов контролов, лежащих на форме. При этом контролы
"предполагают", что на момент вызова этих методов все действия по
инициализации формы уже выполнены.
С уважением, А. Королев
[skipped]
IK>> А это нужно _только_ для базового класса (т.е. только в одном слое
IK>> иерархии), или для произвольного?
Я имел в виду, что это не абстрактная задача, т.е. _только_ в базовом классе
формы появляется такое "раздвоение" Init-а, а скажем в унаследованном от
_form классе уже не потребуется вводить After_AfterFormInit... Тогда вполне
можно пойти на создание вместо Init своего метода, Init в _form объявить
Hidden, и из него рулить вызовами FormInit и AfterFormInit... Вот если на
каждой ступени иерархии потребуется _так_ рулить последовательностью
исполнения этого метода (ну т.е. работать несмотря на то, где в ChildClass
поставят DODEFAULT () и поставят ли вообще :)) - то конечно не напасёшся
имён методов-двойников Init-а, да и не удобно...
AK> Любой произвольный класс должен вести себя таким образом: после
AK> _полной_ отработки кода в методе Init вызывать метод AfterFormInit,
AK> который предназначен для окончательного этапа инициализации контролов
AK> посредством вызова соответствующих методов контролов, лежащих на форме.
AK> При этом контролы "предполагают", что на момент вызова этих методов все
AK> действия по инициализации формы уже выполнены.
Да оно понятно в принципе... Может всё-же Form.Activate задействовать?
[Skipped]
AK> procedure Load
AK> BindEvent(This, "Init", This, "AfterFormInit", 1)
AK> EndProc
AK> Сначала обрадовался, что заработало, потом оказалось
AK> а) Код AfterFormInit иногда не выполнялся (поведение случайное)
AK> б) Иногда (при иерархии глубже трех) получаем Exception C00..5
Я бы ещё пошаманил: привязал бы событие к процедуре _отдельного_
объекта, специально созданного ещё до создания формы.
А проще забить на это и ещё раз субклассировать, чтобы
Proc Init = dodefault()+код из AfterFormInit
With best regards, Sjfx.
AK>> procedure Load
AK>> BindEvent(This, "Init", This, "AfterFormInit", 1)
AK>> EndProc
AK>> Сначала обрадовался, что заработало, потом оказалось
AK>> а) Код AfterFormInit иногда не выполнялся (поведение случайное)
AK>> б) Иногда (при иерархии глубже трех) получаем Exception C00..5
S> Я бы ещё пошаманил: привязал бы событие к процедуре _отдельного_
S> объекта, специально созданного ещё до создания формы.
Пробовал, то же самое причем в тех же случаях.
S> А проще забить на это и ещё раз субклассировать, чтобы
S> Proc Init = dodefault()+код из AfterFormInit
А если _это_ тоже придется субклассировать? Тогда промежуточный _этот_ класс -
родитель вызовет AfterFormInit до полной отработки метода Init класса -
потомка.
С уважением, А. Королев
S>> Я бы ещё пошаманил: привязал бы событие к процедуре _отдельного_
S>> объекта, специально созданного ещё до создания формы.
AK> Пробовал, то же самое причем в тех же случаях.
Вот ить блин!.. мои соболезнования!
S>> А проще забить на это и ещё раз субклассировать, чтобы
S>> Proc Init = dodefault()+код из AfterFormInit
AK> А если _это_ тоже придется субклассировать? Тогда промежуточный _этот_
AK> класс - родитель вызовет AfterFormInit до полной отработки метода Init
AK> класса - потомка.
И проверено, что _так_ всё работает?
Кстати, в VFP-шных фреймворках обычная практика, когда внутрь цепи
субклассирования встраивается пустой класс, который является
"точкой модификации" для программистов-пользователей фреймворков.
Ну и ждём, когда поставишь SP1, сообщи о результатах.
With best regards, Sjfx.
S> From: "Sjfx" <sj...@vpost.ru>
S> Hу и ждём, когда поставишь SP1, сообщи о результатах.
Ура! В SP1 вроде пофиксили! Короче когда в Load формы делаешь
BindEvent(This, "Init", This, "AfterFormInit", 1),
пока не видел случаев, чтоб возникло C5 или AfterFormInit не вызвался (что без
SP на одной из форм возникало в 1 из 2-3 случаев)
Однако другая ошибка все же не исправлена (найдено мною вчера, изложу в
следующем постинге)
С уважением, А. Королев
S>> Hу и ждём, когда поставишь SP1, сообщи о результатах.
AK> Ура! В SP1 вроде пофиксили! Короче когда в Load формы делаешь
AK> BindEvent(This, "Init", This, "AfterFormInit", 1),
AK> пока не видел случаев, чтоб возникло C5 или AfterFormInit не вызвался
AK> (что без SP на одной из форм возникало в 1 из 2-3 случаев)
Упс... Теперь другая форма идет в этой ситуации на вылет с C5 (1 - 2 раза
просто AfterFormInit не вызывается, потом C0000005).
... мать, мать, мать .... - привычно отозвалось эхо :(
С уважением, А. Королев