TObject, демонстрация использования self (ClassType,TClass,self,TList,Pointer,Add, TClass) |
![]() |
![]() |
Автор megabax | ||||||||||||||||
15.10.2009 г. | ||||||||||||||||
TObject, демонстрация использования self (ClassType,TClass,self,TList,Pointer,Add, TClass)Исходники к уроку можно скачать здесь. Сегодня мы изучим функции ClassType. Реализован он очень просто:
Тип PPointer является указателем на указатель и объявлен следующим образом:
А TClass объявлен:
Переменная Self является ссылкой на сам объект. Что бы было лучше понятно, что такое self и для чего он нужен, давайте рассмотрим пример. Предположим, у нас есть некий контейнер объектов, связанный с некоторым компонентом визуального отображения, в котором отображаются объекта нашего контейнера. При изменении любого из объектов в контейнере необходимо перерисовать визуальный объект. Но вот проблема - сам объект "не знает", что он принадлежит контейнеры. Как решить эту проблему? Логично предположить, в объекте нужно предусмотреть некоторое поле, указывающее на контейнер, которое будет заполнятся при добавлении объекта в контейнер. Можно каждый раз, когда добавляем, еще и "не забыть" присвоить указатель на контейнер. Но согласитесь, это не очень удобно. А вот как же сделать так, что бы эти действия производить в одном методе? Как раз с помощью указателя self. Давайте попробуем написать класс контейнер, содержащий слова. При измении любого слова в контейнере список слов должен обновиться. Для начала объявим объявим класс слова и класс контейнера:
Теперь немножко комментариев к коду. Класс TWordSelfDemo у нас будет хранить слово (его текст). Для задания слова используем свойство word, которое имеет метод для записи SetWord. При реализации этого метода мы предусмотрим обновление визуального компонента, связанного с контейнером. Класс TWordsContainerSelfDemo - собственно говоря, сам контейнер. Это класс, дочерний от TList. В нем переопределены методы Add и Delete, а так же добавлен метод Refresh для обновления связанного с контейнером визуального компонента. Для связи с визуальным компонентом используется свойство ListBox, устанавливаемое методом SetListBox. А теперь перейдем к реализации. Опишем метод SetWord
В данной процедуре происходит проверка, что мы меняем содержимое свойства Word - если пытаемся записать повторно то же самое слово - ничего не делаем. Затем присваиваем новое значение внутреннему полю и запускаем метод Refresh класса контейнера. При чем стоит обратить внимание на то, что нужно еще и убедиться, что наше объект действительно находиться в контейнере - значение поля FOwner проверяем на nil. Все, у класса слова у нас только один метод. Мы его реализовали. Теперь займемся контейнером. Реализуем его метод Add:
В данной функции мы вызываем метод Add родительского класса (TList), затем устанавливаем указатель на себя при помощи ключевого слова self: TWordSelfDemo(Item).FOwner:=self; И, наконец, обновляем визуальный компонент - вызываем refresh. Сам метод refresh будет у нас выглядеть так:
В нем мы очищаем визуальный компонент, а затем в цикле добавляем в него все хранящиеся в контейнере слова. И, наконец, последние два метода, они комментариев, думаю, не требуют:
А теперь сделаем форму*: Саму форму назовем SelfDemoForm, кнопочки btnAdd (добавить), btnDelete (удалить) и btnEdit (редактировать). Сроку для ввода слова назовем edWord, а сипоск слов (компонент TListBox) обзовем lbWords. Теперь напишем для наших кнопок обработчики событий:
но это еще не все, нам нужно объявить в классе формы поле контейнера и написать обработчики события создания и удаления формы:
Все, теперь можно запустить пример (исходники можно скачать здесь):
И так, мы с вами поняли, что же такое указатель self. Теперь вернемся к нашему пресловутому TObject. Рассмотрим еще раз строку: Pointer(Result) := PPointer(Self)^; Мы присваиваем результату функции значение, находящееся там, куда указывает self, при чем сам указатель мы преобразуем к PPointer, поскольку прямое присваивание вызовет у нас ошибку на этапе компиляции: Pointer type required (ожидается тип Pointer). Что же у нас содержаться по адресу, на который указывает self? А там у нас находиться, собственно говоря, сам класс (TClass). - Для чего его можно использовать на практике? - спросите вы. - Допустим, - отвечу я, - вы хотите создать экземпляр класса неизвестного заранее типа. Вы передаёте в неё переменную классового типа и указатель на результат. Практически в любой программе используется метод:
где TComponentClass объявлен как
Другой случай: в TTreeView Вы можете в обработчике события задать своего потомка TTreeNode, с дополнительными свойствами:
Но это мы уже рассмотрим в следующем уроке. Скриншоты, помеченные знаком * , являются цитатами и иллюстрациями программного продукта "Delphi", авторское право на который принадлежит "Borland Software Corporation".
|
||||||||||||||||
Последнее обновление ( 24.05.2013 г. ) |
« След. | Пред. » |
---|