-
Почти что написал компонент - наследник TCustomGroupBox. Это GroupBox, а на нем Edit и кнопочка с точечками. На кнопочку нажимаю - вылазит окошко диалога пути к папке и можно редактировать. Естественно, что при изменении цвета должен меняться цвет и у Edit'а. Написал procedure procedure SetColor(const Value: TColor); override; Дальфи грязно ругаются: "Процедура не найдена в базовом классе". Но вот procedure TControl.SetColor(Value: TColor); Никак не пойму, как это процедура не найдена и как с этим бороться?
-
> procedure SetColor(const Value: TColor); override
override можно только то, что virtual;
Тебе проще написать свойство Color у своего компонента и внутри его вызвать Edit.Color := Value;
-
Игорь, так ведь я пробовал и без override, а там вызывал Inherited. Тоже не получалось. И о свойстве Color я, конечно, думал. Но только что в нем написать? SetColor(const Value: TColor); begin FEdit.Color := Value; //Это понятно //А дальше что? Если я напишу Color := Value просто стек переполню и всё. end; Просто как-то не хочется заставлять перерисовываться GroupBox, который и без меня отлично рисуется. Ещё раз: компонент - это GroupBox с Edit'ом и кнопочкой и ну, конечно, функциональностью. Понимаю, можно свойство как-то иначе обозвать и всё. Но дурацкие названия противоречат же всему просто.
-
> Игорь, так ведь я пробовал и без override, а там вызывал > Inherited. Тоже не получалось. И о свойстве Color я, конечно, > думал. Но только что в нем написать? > SetColor(const Value: TColor);
inherited Color := Value ?
-
Какой Вы умный, Игорь. Ну да, а метод чтения function TStFolderDialog.GetColor: TColor; begin Result := Inherited Color; end;
:)
-
Перехватите CM_ColorChanged
-
> inherited Color := Value ? > Какой Вы умный (...)
Попробовали хотя бы? Неужели не работает?
type
TMyLabel = class (TLabel)
private
procedure SetColor(AValue : TColor);
published
property Color write SetColor;
end;
procedure TMyLabel.SetColor(AValue : TColor);
begin
inherited Color := AValue;
end;
-
Пробывал, не работает !!! var L: TMyLabel;
begin
L := TMyLabel.Create(nil);
TLabel(L).Color := clRed;
L.Parent := Form1;
end;
-
> capkoh © (02.04.08 13:09) [6]
Что будет, если на форме лежит компонент TMyLabel, а его пользователь (то есть, прикладной программист) напишет, например, такой код:
if Components[i] is TLabel then TLabel(Components[i]).Color := clRed;
Чей метод SetColor будет вызван?
=================
Попытка перекрыть свойство или статический метод - это довольно распространенная ошибка. Их нельзя перекрыть, их можно только закрыть - но в этом случае поведение компонента не будет однозначным, а будет зависеть от того, к какому типу приведена ссылка на него (или с каким типом она объявлена). Что, конечно же, недопустимо.
-
> TStas
Правильное решение - в [5].
-
> Семеныч (02.04.08 14:05) [9] > Правильное решение - в [5].
:)))
-
> [8] Семеныч (02.04.08 14:04)
Понял свою ошибку.
-
Да всё работает чудестно. Я и написал, что Шевченко умный. Такое простое решение придумал, но, главное, я не знал, что можно так делать. За это я спасибу ему написал.
-
> TStas © (02.04.08 22:33) [12] Чудесно, говорите? А Вы напишите вот что:
type
THackGroupBox = class(TCustomGroupBox);
...
THackGroupBox(YourComponent).Color := clRed;
И посмотрите, сработает ли Ваш метод SetColor.
-
Вы, наверное, ошиблись. Чтобы доказать, что метод не работает, нужно написать:
type
THackGroupBox = class(TGroupBox);
...
TGroupBox(YourComponent).Color := clRed;
У TCustomGroupBox свойство Color недоступно, потому TGroupBox пишу. Или [7].
-
> capkoh © (03.04.08 18:58) [14]
> Вы, наверное, ошиблись.
"Эт вряд ли". © тов. Сухов. :о)
> У TCustomGroupBox свойство Color недоступно
Объявление THackGroupBox и приведение класса к THackGroupBox дает доступ к секции protected.
> потому TGroupBox пишу
И будет ошибка. В сабже сказано, что компонент наследуется от TCustomGroupBox, поэтому потомком TGroupBox он НЕ является и приводить его к этому классу нельзя.
-
Вот так вы говорите сделать:
type
THackGroupBox = class (TCustomGroupBox)
private
procedure SetColor(AValue : TColor);
published
property Color write SetColor;
end;
var
G : THackGroupBox;
procedure THackGroupBox.SetColor(AValue : TColor);
begin
G.Caption := 'THackGroupBox';
inherited Color := AValue;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
G := THackGroupBox.Create(Self);
G.Caption := 'TGroupBox';
THackGroupBox(G).Color := clRed; G.Parent := Self;
end;
? Но тогда я не понимаю, чем вызов
THackGroupBox(G).Color := clRed;
будет отличатся от
G.Color := clRed;
если
G : THackGroupBox;
? При выполнении кода выше, вызывается THackGroupBox.SetColor(), а не TCustomGroupBox.SetColor(), как, видимо, вы полагаете. Тем не менее, вашей целью, как я понимаю, является доказательство того, что потенциально появляется неоднозначность, как описано в [8]. Мне это непонятно. Или я совсем ничего не понимаю? (такое тоже может быть) > У TCustomGroupBox свойство Color недоступно, потому TGroupBox > пишу.
Приводя YourComponent так в [14]
TCustomGroupBox(YourComponent).Color := clRed;
получим ошибку компиляции
[Error]: Undeclared identifier 'Color'
при этом в [14]
THackGroupBox = class(TGroupBox);
так что ошибки наследования не будет, и приведение к TGroupBox оправдано. Получается, что наследоваться от TCustom* и применять метод [3], [6] для свойств вполне можно, если они невидимы в базовом классе. Это верно?
-
> capkoh © (03.04.08 20:44) [16] > Вот так вы говорите сделать. Нет, не так. Код в [13] - полный, ничего больше не нужно. Только объявить Hack-класс (без всякой реализации) и привести компонент к нему. > При выполнении кода выше, вызывается THackGroupBox.SetColor(), а не > TCustomGroupBox.SetColor() Эх... писали-писали, читали-читали... и все с начала... С каким типом объявлена переменная G, тот метод и вызывается. Объявите var G: TCustomGroupBox; и результат будет другим. О чем и речь. > ошибки наследования не будет Есть сабжевый компонент:
unit YourComponentUnit;
type
TYourComponent = class(TCustomGroupBox)
...
end;
И есть объявление Hack-класса (только объявление, больше ничего).
unit Unit1;
type
TTHackGroupBox = class(TCustomGroupBox);
1. В Unit1 свойство TCustomGroupBox.Color недоступно, а свойство THackGroupBox.Color - доступно. 2. Класс TYourComponent является классом TCustomGroupBox, но НЕ является классом TGroupBox. Приводить его к TGroupBox нельзя, потому что класс TGroupBox от класса TCustomGroupBox (предка компонента) отличается. 3. Хотя класс TYourComponent классом THackGroupBox тоже не является, приводить его к классу THackGroupBox можно - потому что класс THackGroupBox от класса TCustomGroupBox (предка компонента) по сути НЕ отличается. > Получается, что наследоваться от TCustom* и применять метод [3], [6]> для свойств вполне можно, если они невидимы в базовом классе Нельзя. Но если хочется ловить неожиданные баги в неожиданных местах - то можно.
-
Повторяю ещё раз !!! Перекрыть метод изменения цвета нельзя, потому что но не виртуальный. Следовательно, создание одноимённого свойства не приводит к тому что родители компонента будут к нему обращаться. Обращение типа TLabel(MyLabel).Color приведёт к обращению к старому методу чтения и старому методу записи, при этом новый метод записи попросту игнорируется поскольку он не унаследован и не переопределённ. Правильное решение перехватить событие CM_ColorChanged и обработать в нём свои изменения.
-
> Нет, не так. Код в [13] - полный, ничего больше не нужно.
Теперь понял, надеюсь, окончательно. Я не знал, что можно подобраться к SetColor() в TCustom*.
> при этом новый метод записи попросту игнорируется
Это я понял ещё в [11].
Семеныч, DimaBr, спасибо за разъяснения (хотя я и не топикстартер :).
-
> capkoh © (04.04.08 11:11) [19] > можно подобраться к SetColor() в TCustom*.
Не совсем так. Если метод объявлен в секции private, то подобраться нему напрямую из другого модуля нельзя никак (по крайней мере, легальными способами). Но через Hack-класс можно подобраться ко всей секции protected - и если в ней объявлено свойство, то через него получаем неявный доступ к методам его записи/чтения, даже когда сами эти методы сидят в private.
-
>можно подобраться ко всей секции protected - и если в ней объявлено свойство, то через него получаем неявный доступ к методам его записи/чтения, даже когда сами эти методы сидят в private ??? Можно подробнее?
-
> TStas © (08.04.08 21:30) [21]Дык... куда ж еще-то подробнее? Кидаем на форму TGroupBos и пишем:
type
THackGroupBox = class(TCustomGroupBox);
procedure TForm1.FormCreate(Sender: TObject);
begin
THackGroupBox(GroupBox1).Color := clRed; end;
В первом случае мы пытались использовать свойство TCustomGroupBox.Clolor, а оно находится в protected и поэтому недоступно. Получаем ошибку компиляции. Во втором случае мы использовали свойство THackGroupBox.Clolor. Этот класс является потомком TCustomGroupBox и поэтому видит всю его секцию ptotected. Согласно правилам видимости, эта же секция будет видна в том модуле, где объявлен сам класс THackGroupBox, ниже его объявления. И хотя GroupBox1 классу THackGroupBox не принадлежит, приведение типа здесь безопасно, поскольку GroupBox1 является потомком класса TCustomGroupBox, от которого наш класс THackGroupBox ничем не отличается.
-
А причем здесь private методы? У потомка вызвано свойство из секции protected, которая только для этого и существует. Где же здесь прямое обращение к private методам? Оно опосредованное. То есть мы же не можем вызвать SetColor(clRed).
-
> TStas © (09.04.08 11:43) [23]
Стас, ты ветку читал? В [20] что написано? Не то же самое?
|