Особенности компонентов начинаются с конструктора, который требует указать в качестве аргумента другой компонент:

constructor Create(AOwner: TComponent); virtual;

Этот другой компонент называется владельцем исходного и в дальнейшем может быть доступен через read-only свойство Owner: TComponent. Впрочем, nil в качестве владельца компонента тоже допустим. Каждый компонент может получить доступ к объектам, которыми он владеет, через свойства:

property Components[Index: Integer]: TComponent; property ComponentCount: Integer;

Эти свойства содержат соответственно массив компонентов и его размер. И хотя Owner – это read-only свойство, можно сменить владельца компонента. Для этого надо вызвать public-метод компонента, который нужно сделать владельцем:

procedure InsertComponent(AComponent: TComponent);

Впрочем, не любой компонент может быть владельцем любого другого. В частности, не пытайтесь с помощью InsertComponent сконструировать «замкнутый круг» (A = B.Owner, B = A.Owner) – вы получите Stack Overflow. Таким образом, компоненты в оперативной памяти могут объединяться лишь в «деревья» – структуры, не содержащие циклов и петель.

Зачем нужно владение? Дело в том, что оно предоставляет удобный механизм автоматического высвобождения памяти. Деструктор TComponent устроен таким образом, что он вызывает деструкторы всех компонентов, которыми данный компонент владеет, а те – вызывают деструкторы компонентов, которыми владеют они, и так далее. Сделав A владельцем B, мы можем более не задумываться о вызове B.Free в надлежащем месте кода, поскольку когда разрушится A, разрушится и B. Именно таким образом при вызове деструктора формы высвобождается память, занятая всеми компонентами, находящимися на данной форме.

Класс TComponent предоставляет protected-метод Notification, который можно переопределить в наследнике. Это дает возможность предпринять какие-то действия в момент, когда один компонент становится владельцем другого или перестает быть таковым. Кроме того, с помощью public-метода FreeNotification(AComponent:TComponent) можно «подписать» компонент на «извещение о разрушении» другого компонента. При прямом вызове деструктора некоторого компонента у его владельца, а также у всех тех, которые «подписаны на извещение» о его разрушении, вызывается метод Notification с соответствующими параметрами. Всё это нужно для сохранения целостности возможных перекрёстных ссылок между компонентами.

В завершение надо заметить, что, несмотря на то, что концепция «владения» поддерживает многоуровневую иерархию, на практике почти никогда не создаются системы с большим числом уровней. Чаще всего один компонент владеет многими другими, которые, в свою очередь, не владеют ничем. Так, форма владеет всеми объектами-наследниками TComponent, на ней расположенными, хотя на первый взгляд может показаться, что это не так. Например: хотя любой TAction «входит» в TActionList, если вы проверите значение свойства Action.Owner во время выполнения программы, то обнаружите, что это – форма (которая и является владельцем и TAction, и TActionList). Причины этого будут указаны ниже. Уникальные имена: свойство Name

Другим важнейшим свойством всех компонентов является Name:

property Name: TComponentName;

где тип TComponentName – псевдоним обычной строки. У этого свойства есть две особенности. Во-первых, строка, которой приравнивается Name, должна содержать только большие и малые буквы латинского алфавита, цифры и знаки подчёркивания, и не должна начинаться с цифры. Попытка присвоить этому свойству что-то другое приведёт к ошибке во время выполнения. И, во-вторых, у нескольких компонентов с одинаковыми именами никогда не может быть общего владельца, если только их имена – не пустые строки. Ошибка возникнет при любой попытке задать какому-либо компоненту имя, неуникальное среди компонентов, имеющих того же владельца, или поменять владельца компонента таким образом, что в новой «компании» имя компонента будет неуникальным.

Если вспомнить, что имени компонента, положенного в визуальном редакторе на форму, соответствует имя переменной в классе формы, то эти ограничения станут вполне очевидны.

<<< 0 1 2 3 4 5 6 7 8 >>>
Хостинг от uCoz