| | | | |
Доступ к protected-свойству BorderWidth класса TPageControl. | Полный текст материала
Цитата или краткий комментарий: «... Нестандартный вариант доступа к protected-свойству BorderWidth класса TPageControl. ...» |
Важно:- Страница предназначена для обсуждения материала, его содержания, полезности, соответствия действительности и так далее. Смысл не в разборке, а в приближении к истине :о) и пользе для всех.
- Любые другие сообщения или вопросы, а так же личные эмоции в адрес авторов и полемика, не относящаяся к теме обсуждаемого материала, будут удаляться без предупреждения авторов, дабы не мешать жителям нормально общаться.
- При голосовании учитывайте уровень, на который расчитан материал. "Интересность и полезность" имеет смысл оценивать относительно того, кому именно предназначался материал.
- Размер одного сообщений не должен превышать 5К. Если Вам нужно сказать больше, сделайте это за два раза. Или, что в данной ситуации правильнее, напишите свою статью.
Всегда легче осудить сделанное, нежели сделать самому. Поэтому, пожалуйста, соблюдайте правила Королевства и уважайте друг друга.
Добавить свое мнение.
| | Содержит полезные и(или) интересные сведения | [1] | 0 | 0% | | | | Ничего особенно нового и интересного | [2] | 5 | 35.7% | | | | Написано неверно (обязательно укажите почему) | [3] | 9 | 64.3% | | Всего проголосовали: 14 | | | Все понятно, материал читается легко | [1] | 9 | 100% | | | | Есть неясности в изложении | [2] | 0 | 0% | | | | Непонятно написано, трудно читается | [3] | 0 | 0% | | Всего проголосовали: 9 |
[TPageControl] [Секции private/public/protected/published]
Отслеживать это обсуждение
Всего сообщений: 4711-05-2012 02:40Есть еще вариант реализации:
type
THackPageControl = class(TPageControl);
У этого варианта, оказывается, есть очень правильное название :)
Паблик Морозов: Класс-потомок, созданный в соответствии с этим антипаттерном, выдает по запросу все данные класса-предка, независимо от степени их сокрытия. Название данного анти-паттерна — это каламбур, основанный на созвучии ключевого слова public (паблик), часто означающего открытый доступ к методам и полям класса в объектно-ориентированных языках программирования, и имени пионера-героя Павлика Морозова, известного тем, что он выдал своего отца-кулака занимавшегося вредительством будучи на руководящей должности в советской системе. Источником данного определения является блог пропагандистской направленности.
Отсюда: http://ru.wikipedia.org/wiki/%D0%90%D0%BD%D1%82%D0%B8%D0%BF%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD#.D0.A8.D1.83.D1.82.D0.BE.D1.87.D0.BD.D1.8B.D0.B5_.D0.B0.D0.BD.D1.82.D0.B8-.D0.BF.D0.B0.D1.82.D1.82.D0.B5.D1.80.D0.BD.D1.8B |
|
16-05-2009 01:42В будущих версиях Delphi смещение свойства может измениться
В Delphi 2009 (Win32) смещение поля BorderWidth теперь равно 432, а не 364, как было раньше. |
|
25-01-2007 22:27>>>Geo
Билдер создает DFM-файл, содержащий данные об инициализации компонент (кстати, до сих пор не знаю, как именно происходит инициализация).
Если интересно, посмотрите в модуле Classes классы TReader & TWriter, а также TStream.ReadComponent(res) & TStream.WriteComponent(res). Иногда их можно использовать с пользой. Сюда же можно отнести и метод TPersistent.DefineProperties. |
|
12-01-2007 12:28>>> Вообще, я был настолько уверен, что этот способ известен всем, что само появление статьи вызвало немалое удивление
Я тоже был уверен, что способ модификации базовых классов с сохранением оригинальных имен известен всем. А вот заработал "плюху" за то, что долго молчал и не рассказывал такую полезную штуку ;-) |
|
12-01-2007 12:15Вообще, я был настолько уверен, что этот способ известен всем, что само появление статьи вызвало немалое удивление. |
|
12-01-2007 08:33>>> Антон, ну ты же знаешь, что чукча не читатель...
М-дя... Мне тоже что ли написать здесь еще раз про использование Hack-класса для доступа к protected-полям классов, выдав это за мое сокровенное знание? ;-) |
|
12-01-2007 05:49> Антон Григорьев
Антон, ну ты же знаешь, что чукча не читатель...
:о)
|
|
05-01-2007 08:59Для получения доступа к секции protected нет никакой нужды прибегать к сомнительным методам, все делается гораздо проще и (самое главное!) гораздо надежнее.
Ух ты! А мужики-то и не знают! Спасибо, Юрий, ты открыл нам глаза ;)
Только чужие комментарии к статье тоже иногда не вредно читать :) |
|
05-01-2007 05:53Для получения доступа к секции protected нет никакой нужды прибегать к сомнительным методам, все делается гораздо проще и (самое главное!) гораздо надежнее.
Объявляем фиктивный класс:
type
TFriendClass = class(TSomeClass);
После чего в данном модуле становится доступной секция protected класса TSomeClass:
var
Obj: TSomeClass;
...
TFriendClass(Obj).ProtectedMethod(...);
TFriendClass(Obj).ProtectedProperty ...;
|
|
27-12-2006 09:42>> По поводу goto был длительный спор на Базарной Площади ...
Это я просто пошутил мимоходом, никто флейм разводить не собирался |
|
27-12-2006 07:57>>> Да я же уже сказал, что прямой опасности я не вижу...
Пардон, ответ писал среди ночи, и не заметил, что речь идет об отношении на уровне чувств, а не на уровне разума. Потом понял, но было уже поздно.
Зато высказал все соображения по поводу безопасности данного способа ;-)
>>> И чем вам goto не угодил?
>>> Антон - зря вы так к goto
По поводу goto был длительный спор на Базарной Площади в теме "Вопросы оптимизации кода" (http://delphikingdom.ru/asp/talktopic.asp?ID=356 ) Если интересно, можно почитать. А здесь лучше этот вопрос не поднимать: по степени "флеймогонности" данный вопрос стоит где-то рядом с темой "Паскаль против Си" ;-) |
|
27-12-2006 06:37Geo, не бойся, модуль.объект - это нормальное именование в полном пространстве имен, и Борланд никуда это не денет
Способ от Ins-а - вполне адекватный прием обмана RTTL с дизайнером, в конце концов им никто не обещал что они должны по своим именам находить именно компоненты из VCL. Хотя хак можно прикрыть если переписать дизайнер так чтобы он пользовался полными именами, или, к примеру, Борланд может использовать отдельную немодифицируемую программистом секцию uses. Ну это так... философия...
Антон - зря вы так к goto (укр. бэйсик "пыди_на" :-) У хорошего мастера каждый ржавый гвоздик в дело идет :-))) |
|
25-12-2006 02:32
Но вот сложить два и два я, напрмер, сам не догадался. Если нам в одном модуле нужен модифицированный компонент, а в другом -- оригинальный, то управлять этим мы можем помещая имя модуля с модифицированным компонентом в разное место в списке uses.
Тут важно другое.
Мы объявляем наследника с тем же именем что и родитель, и компилятор корректно обрабатывает это (работает наш код).
В некоторых случаях, важно иметь взаимно исключающую функциональность некоторого класса, причем функциональность не визуальную.
Простейший способ для не визуальных и не компонетных классов это создать наследников, объявить классовую ссылку и при создании параметризировать ее нужным классом. Для компонентов, нужно больше теловижений, этих наследников нужно зарегистрировать в палитре, и бросать на форму.
А в предложенном способе, мы избавлены от этого. Нам нужно будет только в коментарии описать что этот модуль должен следовать после того и все.
Плюсы
Во первых мы не модифицируем исходник, а значит при смене версии делфи или библиотеки мы застрахованы от потери наших изменений.
Во вторых, мы имеем гибкость в том что у нас используется фактически.
Минусы
1. Относительный минус этого всего в том, что этот способ не документирован.
2. если способ не знаком программисту может сбить его с толку.
А у меня сейчас, например, в модуле кроме модифицированного компонента имеется еше ряд полезных функций, которые могут пригодиться даже в том случае, когда используется оригинальный компонент.
Ну это не проблема. Это стандартная ситуация при написании кода. Просто сделается рефакторинг и все. Эти функции выделятся в отдельный модуль, и если там нет инициализации/финализации то добавление его безвредно. Компилятор отсечет не используему функциональность.
для Антон Григорьев
Да я же уже сказал, что прямой опасности я не вижу. Просто такой способ доступа к protected свойствам вызывает у меня чувство брезгливости. Ну, примерно как goto.
И чем вам goto не угодил? Обычный оператор который может и должен использоваться в нужном месте. Как и все остальное в этом мире. А миф о вреде goto был сформирован из-за программистов которые писали бездумно. И в результате в наше время мы можем видеь код который написан в ООП стиле, также не сопровождаемый, как и код который написан из-за черезмерного увлечения goto. :(
|
|
23-12-2006 00:48Geo:
Да я же уже сказал, что прямой опасности я не вижу. Просто такой способ доступа к protected свойствам вызывает у меня чувство брезгливости. Ну, примерно как goto. |
|
22-12-2006 17:44Антон! А Вам приходилось пользоваться другими инструментами визуального проектирования. Желательно, в более ранние времена, когда средства были проще. Я вот помню такую утилитку для Клиппера, которая называлась UI. На экране рисуешь окошки, а потом нажимаешь кнопку, и в файл сбрасывается автоматически сгенеренный код, которые реализует все эти окошки. С этим кодом потом можно делать все, что хочешь. Утилите на это начхать: она номер отработала и довольна.
Собственно говоря, Дельфи от этого ушла не очень далеко. Ее билдер -- это такая же программудина, которая позволяет таскать компоненты по формочкам, а результаты сбрасывает в файл PAS. Принципиальных отличий от UI я насчитал два:
1. Билдер проверяет наличие в коде "своих" компонент и определенных методов, которые являются обработчиками событий этих компонентов.
2. Билдер создает DFM-файл, содержащий данные об инициализации компонент (кстати, до сих пор не знаю, как именно происходит инициализация).
Может быть я что-то упустил, так что дополняйте.
Я выделил эти моменты потому, что все сотальные моменты приближайшем рассмотрении сомнительными не являются, а представляют собой использование документированных возможностей Delphi. Не думаю, что в очередной версии Borland запретит использовани расширенных имен (модуль плюс имя).
По билдеру. Пока, насколько я мог видеть, он работает именно так: во-первых, помогает генерить код (но на этапе компиляции, билдер уже не делает ничего; работает только компилятор). И еще создает файл с начальными значениями определенных компонент (ну, нет там больше ничего; можно выбросить из модуля строчку {$R *.DFM} и все-равно компилятор сработает без ошибок). Только потом замаешься в run-time компоненты по местам расставлять.
Угроза может идти только с этой стороны. Либо билдер будет создавать какую-то существенную часть, необходимую для правильной компиляции кода (которую нельзя сделать в тексте программы), либо билдер будет принимать участие не только в написании текста на Delphi, но и возьмет на себя часть функций компилятора.
Ни в то, ни в другое я пока не верю. А Вы?
P.S. Столько материала набралось в обсуждении, что уже пора статью писать ;-) |
|
22-12-2006 12:21Один раз в обсуждении на КС Антон Григорьев высказал сомнения в правомерности использования такого подхода, но, видимо, его все же убедили, что все корректно.
Не то чтобы убедили... Я считаю эту возможность нехорошей дыркой - что-то не до конца продумано в языке Delphi, если такое становится возможным. А ещё больше мне не нравится сам факт того, что доступ к private и protected членам класса имеет код, совершенно к классу не относящийся, а просто находящийся с ним в одном модуле. Да и наличие в языке приведения типов мне тоже не нравится. Но API и VCL построены так, что все эти милые штучки приходится использовать, а потому проводить границу, что от сих до сих я это использую, а вот здесь - уже нет, смысла не вижу. |
|
21-12-2006 18:58>>> Если нам нужен оригиналный компонент, то можно вообще не включать модуль в список uses.
Уп-с... Естественно. Но при условии, что модифицированный компонент находится в специально отведенном для него модуле, в котором больше ничего нет. А у меня сейчас, например, в модуле кроме модифицированного компонента имеется еше ряд полезных функций, которые могут пригодиться даже в том случае, когда используется оригинальный компонент.
>>> Так как если эти типы понадобятся в других модулях, то в них придется ссылаться на модуль с формой. Если этим злоупотреблять, то это очень часто будет приводить к перекрестным ссылкам.
Мысль понятна, хотя с перекрестными ссылками можно бороться используя uses в interface и в implementation. Я обычно всегда стараюсь размещать ссылку на модуль в implementation uses, если это возможно.
Просто у меня до недавнего времени не было случая, когда модифицированный компонент требовался в более, чем одной форме. А нет проблемы, нет и решения ;-) |
|
21-12-2006 17:33Если нам в олном модуле нужен модифицированный компонент, а в другом -- оригинальный, то управлять этим мы можем помещая имя модуля с модифицированным компонентом в разное место в списке uses.
Я бы сказал немного иначе. Если нам нужен оригиналный компонент, то можно вообще не включать модуль в список uses. Дело в другом. Просто я стараюсь избегать объявление каких-либо типов в модулях с формой, а завожу для этого отдельный. Так как если эти типы понадобятся в других модулях, то в них придется ссылаться на модуль с формой. Если этим злоупотреблять, то это очень часто будет приводить к перекрестным ссылкам. |
|
21-12-2006 09:24>>> Наверное имеется в виду это
Да, это именно оно. Просто я принимал участие в обсуждении более тысяи вопросов и не отважился отправиться на поиски на своем диалапе.
>>> А вот за это отобрать у него эту звёздочку, так как знал и столько времени молчал...
Господа, будьте снисходительны. Я на Королевстве меньше двух лет. И способ этот я озвучил всего лишь через 7 месяцев после появления. Неужели семь месяцев молчания достойны такой жестокой кары? ;-)
Кстати, могу отдать половину звездочки Ins'у. За идею вынесения таких переопределенных классов в другой модуль. То, что компилятор просматривает uses в поисках имен в обратном поряке, вещь известная. Но вот сложить два и два я, напрмер, сам не догадался. Если нам в олном модуле нужен модифицированный компонент, а в другом -- оригинальный, то управлять этим мы можем помещая имя модуля с модифицированным компонентом в разное место в списке uses. |
|
21-12-2006 07:39Вообще, здорово было бы, если бы был раздел на Королевстве, специально для подобных фишек. Требования такие.
Да, действительно было бы интересно, какие нибудь "Артефакты" например. Могу предложить пару вещей, только скорее не по Delphi, а по WinAPI... Хотя и по Delphi пара сомнительных, но рабочих методов у меня имеется. |
|
21-12-2006 06:56Вообще, здорово было бы, если бы был раздел на Королевстве, специально для подобных фишек. Требования такие.
1. Способ работает.
2. Способ мало известен.
3. Никто не знает, почему он работает, или возможны побочные эффекты.
А в обсуждениях, исследовать глубже, разгадывать, в чем тайна или находить эти самые побочные эффекты.
А то на КС чего только не увидешь, вот бы собрать все это в одном месте! |
|
21-12-2006 06:20http://www.delphikingdom.ru/asp/answer.asp?IDAnswer=35814
Я впервые этот способ увидел там же. Вот за это Geo надо ещё одну звёздочку привинтить,
Я этим способом вообще пользуюсь с конца 90-х (еще с Delphi 1). А вот за это отобрать у него эту звёздочку, так как знал и столько времени молчал... |
|
21-12-2006 05:56точнее помню где примерно я его первый раз увидел, но не могу найти сам этот вопрос
Один раз в обсуждении на КС Антон Григорьев высказал сомнения в правомерности использования такого подхода, но, видимо, его все же убедили, что все корректно.
Наверное имеется в виду это.
http://www.delphikingdom.ru/asp/answer.asp?IDAnswer=35814
Я впервые этот способ увидел там же. |
|
21-12-2006 05:07>>> Я и спрашиваю, есть ли скрытые грабли :))
Если быть полностью честным, то правильнее было бы ответить: за несколько лет использования такого способа разными людьми на разных версиях Delphi граблей не обнаружено. Я этим способом вообще пользуюсь с конца 90-х (еще с Delphi 1). Один раз в обсуждении на КС Антон Григорьев высказал сомнения в правомерности использования такого подхода, но, видимо, его все же убедили, что все корректно.
Если же попытаться подвести теоретическую базу, то тут мне придется делать некоторые допущения в областях, точную работу которых я не знаю.
Design-Time: При работе в среде в связке дизайнер-редактор ведущим является дизайнер. По сути дела дизайнер -- это самостоятельная программа, которая в процессе работы какую-то информацию сбрасывает в текстовый файл: мы что-то там на формочке двигаем, меняем свойства, а в результате этих действий в текст программы вставляются различные автоматически подготовленные конструкции. А все то, что мы нагородим у себя в тексте руками, на работоспособности дизайнера никак не скажется.
Компиляция: Разруливание дублирования в процессе компиляции определяется строгим порядком поиска имен в юнитах (как там? сначала в текущем модуле, потом в подключенных через uses в обратном порядке). Использование названия модуля для конкретизации имени (напимер, StdCtrls.TEdit) является документированной возможностью Delphi.
Run-Time: Использование вместо базового класса любого его потомка (при условии, что будут использоваться только свойства и методы, определенные в базовом классе) -- позднее связывание -- является одним из основных преимуществ всего объектно-ориентированного программирования. Так что тут все тоже чисто. |
|
20-12-2006 23:46Я и спрашиваю, есть ли скрытые грабли :))
Если это только что открытый способ это один разговор, если давно опробаванный, то другой :) Зря не просматриваете вопросы/ответы на круглом столе, хотябы мельком. уже не помню с какого времени отвечают подобным образом (точнее помню где примерно я его первый раз увидел, но не могу найти сам этот вопрос). |
|
20-12-2006 09:14для Ins и Geo
Я и спрашиваю, есть ли скрытые грабли :))
Если это только что открытый способ это один разговор, если давно опробаванный, то другой :)
Просто меня давно интересовала возможность "подмены" некоторых классов в Runtime. Причем обычно меняю только функциональность, а published свойства не ввожу.
А слет обработчиков или свойств из DFM это мои обнаруженные грабли :( но не с этим способом. Как возникнит необходимость, попробую.
Спасибо за ответы! |
|
20-12-2006 08:56>>> Т.е. на форму в IDE кидаем например TPageControl, а в Runtime подгружается другой компонент с измененной функциональностью, не слетают обработчики событий и свойства из DFM?
Подтверждаю работоспособность варианта от Ins обеими лапами. Это мой любимый прием, так как практически под каждый проект приходится понемногу модифицировать стандартные компоненты, а писать на каждый случай новый компонент и размещать его в палитре -- не хочется. Но и размещать его на ворме в run-time -- тоже ломает.
Кстати, как раз сегодня в проекте переписал таким способом сласс TForm, чтобы убрать у него механизмы изменения размера формы (должена быть постоянного размера). Все работает, как часы ;-) |
|
20-12-2006 07:52Т.е. на форму в IDE кидаем например TPageControl, а в Runtime подгружается другой компонент с измененной функциональностью, не слетают обработчики событий и свойства из DFM?
Ничего не слетает. Сами попробуйте. При загрузке формы из DFM будет создан экземпляр наследника. Так как у него тоже есть одноименные свойства и события, они будут корректно загружены. Другое дело, что в Design-time вы не получите доступ к новым опубликованным свойствам, так как среда считает, что используется класс-предок, но в Run-time - пожалуйста. |
|
20-12-2006 07:17Для Anton Duzenko
Так код писать нельзя. При переходе на новую версию Delphi или простого перемещения поля в другое место в базовом классе вы отгребете массу глюков. Насколько часто вы лазите в код чужих компонент или даже своих давно написанных? Я очень редко, только когда отладка показывает что нужно переходить от черного ящика к прозрачному...
для Админов.
Может пометить в этой статье что так поступать не стоит, изначально?
А объяснение почему мол смотрите в обсуждении.
для MrZeRo
А почему народ не хочет еще проще?
TStatusBar(PageControl1).BorderWidth := 20;
потому что это тот же самый хак, который использовал Anton Duzenko. Только выраженный в более правильной форме. Будет работать для всех классов, унаследованых от базового, до тех пор, пока не попадется модуль откомпилированный с другим расположением поля отвечающего за BorderWidth.
Особенно опасно, если вы используете комерческую библиотеку без исходных кодов. Если с исходниками для восстановления работоспособности вам достаточно будет сделать полный Build библиотеки, то в варианте только DCU, будете получать непонятные глюки или не возможность компиляции проекта.
Хотя THackPageControl = class(TPageControl) тоже как-то не очень. Как логически это понять человеку со стороны, знакомому с ООП и не знакомому с Delphi?
Это означает что нужно перестать программировать методом научного тыка, а нужно прочитать книжки по Delphi и ООП или осмыслить свои знания. В наследнике мы имеем полный доступ к protected частям, что еще нужно для понимания?
THackPageControl = class(TPageControl) является наиболее правильным способом получения доступа к защищенным методам/свойствам/полям из внешней среды без создания наследника.
И этот способ полностью соответствует духу ООП.
для Ins
первое сообщение довольно интересное, как оно в эксплуатации с визуальным наследованием?
Т.е. на форму в IDE кидаем например TPageControl, а в Runtime подгружается другой компонент с измененной функциональностью, не слетают обработчики событий и свойства из DFM?
|
|
19-12-2006 10:14Хотя THackPageControl = class(TPageControl) тоже как-то не очень.
Возможно, но этот способ по крайней мере используется в самой VCL, так что "индульгенция" от Borland-а получена :)
"Правильней" всего написать наследника TPageControl с опубликованным свойством
Фактически это то же самое, только не выносится свойство в public, а видимость защищённых свойств внутри модуля хорошо документирована и врядли исчезнет из будущих версий. |
|
19-12-2006 07:53Так нельзя делать, потому что нак нельзя делать никогда. |
|
19-12-2006 07:02Я про этот финт давно читал на каком-то околоборландовском форуме, там народ, вроде как приближенный к разработчикам Delphi, говорил, что в обозримом будущем будет работать. Но некрасиво, согласен.
Хотя THackPageControl = class(TPageControl) тоже как-то не очень. Как логически это понять человеку со стороны, знакомому с ООП и не знакомому с Delphi? "Правильней" всего написать наследника TPageControl с опубликованным свойством, а все остальные способы стоят один другого и в плане "корректности", и в плане поддержки в следующих версиях. |
|
19-12-2006 05:11А почему народ не хочет еще проще?
TStatusBar(PageControl1).BorderWidth := 20;
Потому как это чревато возможными глюками на новых версиях VCL, да и поддерживать такой код нереально: ну какое отношение имеет TStatusBar к PageControl1. Вобщем это не намного лучше изначального варианта. |
|
19-12-2006 04:50А почему народ не хочет еще проще?
TStatusBar(PageControl1).BorderWidth := 20; |
|
14-12-2006 03:45Спасибо за внимание к моему опусу. Из обсуждения вынес для себя много полезного |
|
11-12-2006 06:10Мы пойдем другим путем.
Создаем новый тестовый проект, кидаем на форму разные компоненты, в которых BorderWidth опубликовано (StatusBar, TreeView, etc), и пишем код, измеряющий расстояние между адресом объекта и адресом его свойства BorderWidth. Для всех компонентов он один и тот же - 364 байта. Делаем индуктивный вывод, о том, что у всех наследников TWinControl на 364 байте находится BorderWidth. Проверяем на PageControl'e.
Работает :)
Ребята, я бы со всем вышеизложенным легко согласился, если бы мы в указанном примере меняли значение переменной, расположенной по фиксированному адресу внутри экземпляра класса. Но так как задача у нас - изменить значение свойства (я надеюсь, все присутствующие понимают, что вызов TWinControl.BorderWidth := 1234 на самом деле вызывает TWinControl.SetBorderWidth(1234)) то у меня возникает вопрос к автору статьи: по указанному смещению (364 байта) находится private-переменная FBorderWidth экземпляра класса (если так, то изменив ее значение, мы не добьемся немедленной перерисовки внешнего вида контрола) или точка входа в процедуру SetBorderWidth? Во втором случае автору следовало бы указать в статье способ вызова этой процедуры (например использовать вызов через переменную процедурного типа, которой заранее присвоить адрес "адрес экземпляра PageControl плюс смещение"?)
В общем, автору "низачот" :)
|
|
11-12-2006 04:14Методика "хакнутого" класса (THackedClass=class(TBaseClass)) стара настолько насколько практически стара Дельфи, впервые я увидел такое решение в наидревнейшем RxLib-е, чего вы так все восхитились "новостью" от Эрика?
Антон, не надо публиковать такие вещи, пожалуйста! А то будет как с одной милой статьей про потоки. Суть была такая, одному человеку не давали покоя лавры Архангельского, и он написал статью "как использовать потоки в Дельфи (TThread)" (ну, за точность названия не ручаюсь, но суть примено такая). Так вот, как (по его версии) надо использовать наследника TThread:
procedure TMyThread.MyThreadedWork;
begin
...
end;
procedure TMyThread.Execute; override;
begin
Synchronize(MyThreadedWork);
end;
Вам нравится? И мне весело. А ведь статья тогда расползлась по сети, у многих начинающих программистов я ее видел в папочке с документацией для "настольного чтения"...
|
|
11-12-2006 02:24Метод предложенный в статье, можно(но только очень аккуратно) использовать
для доступа к приватным полям класса.
А для protected нужно использовать способы Ins и Erik Ivanov |
|
09-12-2006 02:47Сама статья полезна как пример как НЕ надо делать.
А вот обсуждение предложило два решения одно из которых (Erik Ivanov) очень изящно и мне понравилось. Раньше я таким трюком не пользовался. Но возьму на заметку. |
|
09-12-2006 00:26При принятии решения, публиковать ли эту статью, я голосовал за, потому что считал, что из этого может получиться интересное обсуждение. Теперь вижу, что ошибся - решение, предложенное в статье, настолько очевидно некорректное и настолько проигрывает решениям Ins'а и Erik'а Ivanov'а, что обсуждать-то, собственно, и нечего, игра получается в одни ворота. |
|
08-12-2006 19:42Помоему нужно на сайте открыть специальный раздел "Программирование для лентяев" и туда подобный материал публиковать! |
|
08-12-2006 11:18Потому, что так программировать нельзя. |
|
08-12-2006 10:52Не пойму, почему оценки содержания такие скромные. Я поставил "написано неверно". Не потому, что работать не будет. А потому, что это совершенно неправильный способ программирования. Живой пример того, как не надо программировать. Написав так один раз, рискуем огрести кучу проблем в дальнейшем. |
|
08-12-2006 10:49Только вы забыли перенести свойство в public (но я вас понял) :)
А нет, виноват! Ничего вы не забыли :) Если в том же модуле, то все верно! |
|
08-12-2006 10:40Erik Ivanov
Согласен, если нужно просто опубликовать свойство, а не добавить/перекрыть методы или новые свойства, то ваш вариант даже лучше. Только вы забыли перенести свойство в public (но я вас понял) :) |
|
08-12-2006 10:35В другой версии delphi работать небудет!
Есть еще вариант реализации:
type
THackPageControl = class(TPageControl);
В томже модуле
THackPageControl(PageControl1).BorderWidth - доступно. |
|
08-12-2006 10:24Вообще, это очень грязный прием, противоречащий идеологии ООП. Я противник таких штучек. В будущих версиях Delphi смещение свойства может измениться и перенос программы на новую среду станет затруднительным. Во-вторых, компонент не получит и не обработает сообщение CM_BORDERCHANGED. Есть способы проще и универсальнее, как раз сегодня обсуждалось на КС:
unit MyPageControl;
uses ComCtrls;
type
TPageControl = class(ComCtrls.TPageControl)
public
property BorderWidth;
end;
В модуле с формой:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, MyPageControl;
type
TForm1 = class(TForm)
PageControl1: TPageControl;
private
public
end;
...
Вот и все! Свойство BorderWidth доступно в Run-time. |
|
|
|