Sources
Delphi Russian Knowledge Base
DRKB - база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Метаклассы

01.01.2007

Статья: Объектно-ориентированное программирование (ООП)

ССЫЛКИ НА КЛАССЫ

Язык Object Pascal позволяет рассматривать классы как своего рода объекты, которыми можно манипулировать в программе. Такая возможность рождает новое понятие - класс класса; его принято обозначать термином метакласс.

Для поддержки метаклассов введен специальный тип данных - ссылка на класс (class reference). Он описывается с помощью словосочетания class of, например:

type
  TResourceGaugeClass = class of TResourceGauge;

Переменная типа TResourceGaugeClass объявляется в программе обычным образом:

var
  ClassRef: TResourceGaugeClass;

Значениями переменной ClassRef могут быть класс TResourceGauge и все порожденные от него классы. Допустимы, например, следующие операторы:

ClassRef := TResourceGauge;
ClassRef := TDiskGauge;
ClassRef := TMemoryGauge;

По аналогии с тем, как для всех классов существует общий предок TObject, у ссылок на классы существует базовый тип TCIass:

type TCIass = class of TObject;

Переменная типа TCIass может ссылаться на любой класс.

Практическая ценность ссылок на классы состоит в возможности создавать программные модули, работающие с любыми классами объектов, даже с теми, которые еще не разработаны.

МЕТОДЫ КЛАССОВ

Метаклассы привели к возникновению нового типа методов - методов класса. Метод класса оперирует не экземпляром объекта, а непосредственно классом. Он объявляется как обычный метод, но перед словом procedure или function записывается зарезервированное слово class, например:

type
  TResourceGauge = class
    ...
    class function GetClassName : string;
  end;

Псевдопараметр Self, передаваемый в метод класса, содержит не ссылку на объект, а ссылку на класс, поэтому в теле метода нельзя обращаться к полям, методам и свойствам объекта. Зато можно вызывать другие методы класса, например:

class function TResourceGauge.GetClassName: string;
begin
  Result := ClassName;
end;

Метод ClassName объявлен в классе TObject и возвращает имя класса, к которому применяется. Очевидно, что надуманный метод GetClassName просто дублирует эту функциональность для класса TResourceGauge и всех его наследников.

Методы класса применимы и к классам, и к объектам. В обоих случаях в параметре Self передается ссылка на класс объекта. Пример:

var
  Gauge: TResourceGauge;
  S: string;
begin
  { Вызов метода с помощью ссылки на класс }
  S := TDiskGauge.GetClassName; { S получит значение 'TDiskGauge' }
  Gauge := TDiskGauge.Create('С');
  { Вызов метода с помощью ссылки на объект }
  S := Gauge.GetClassName;    { S получит значение 'TDiskGauge' }
end;

Методы классов могут быть виртуальными. Например, в классе TObject определен виртуальный метод класса Newlnstance. Он служит для распределения памяти под объект и автоматически вызывается конструктором. Его можно перекрыть в своем классе, чтобы обеспечить нестандартный способ выделения памяти для экземпляров. Метод Newlnstance должен перекрываться вместе с другим методом Freelnstance, который автоматически вызывается из деструктора и служит для освобождения памяти. Добавим, что размер памяти, требуемый для экземпляра, можно узнать вызовом предопределенного метода класса InstanceSize.

ВИРТУАЛЬНЫЕ КОНСТРУКТОРЫ

Особая мощь ссылок на классы проявляется в сочетании с виртуальными конструкторами. Виртуальный конструктор объявляется с ключевым словом virtual. Вызов виртуального конструктора происходит по фактическому значению ссылки на класс, а не по ее формальному типу. Это позволяет создавать объекты, классы которых неизвестны на этапе компиляции. Механизм виртуальных конструкторов применяется в Delphi при создании форм и компонентов.

На этом закончим изучение теории объектно-ориентированного программирования и в качестве практики рассмотрим несколько широко используемых инструментальных классов Delphi. Разберитесь с их назначением и работой. Это поможет глубже понять ООП и пригодится на будущее.

КЛАССЫ ОБЩЕГО НАЗНАЧЕНИЯ В DELPHI

Как показывает практика, в большинстве задач приходится использовать однотипные структуры данных: списки, массивы, множества и т.д. От задачи к задаче изменяются только их элементы, а методы работы сохраняются. Например, для любого списка нужны процедуры вставки и удаления элементов. В связи с этим возникает естественное желание решить задачу «в общем виде», т.е. создать универсальные средства для управления основными структурами данных. Эта идея не нова. Она давно пришла в голову разработчикам инструментальных пакетов, которые быстро наплодили множество вспомогательных библиотек. Эти библиотеки содержали классы объектов для работы со списками, коллекциями (динамические массивы с переменным количеством элементов), словарями (коллекции, индексированные строками) и другими «абстрактными» структурами. Для Delphi тоже разработаны аналогичные классы объектов. Их большая часть сосредоточена в модуле Classes. Наиболее нужными для вас являются списки строк (TStrings, TStringList) и потоки (TSream, THandleSream, TFileStream, TMemoryStream и TBIobStream). Рассмотрим кратко их назначение и применение.

КЛАССЫ ДЛЯ ПРЕДСТАВЛЕНИЯ СПИСКА СТРОК

Для работы со списками строк служат классы TStrings и TStringList. Они используются в библиотеке VCL повсеместно и имеют гораздо большую универсальность, чем та, что можно почерпнуть из их названия. Классы TStrings и TStringList служат для представления не просто списка строк, а списка элементов, каждый из которых представляет собой пару строка-объект. Если со строками не ассоциированы объекты, получается обычный список строк.

Класс TStrings используется визуальными компонентами и является абстрактным. Он не имеет собственных средств хранения строк и определяет лишь интерфейс для работы с элементами. Класс TStringList является наследником TStrings и служит для организации списков строк, которые используются отдельно от управляющих элементов. Объекты TStringList хранят строки и объекты в динамической памяти.

Свойства класса TStrings описаны ниже.

Наследники класса TStrings иногда используются для хранения строк вида Имя=3начение, в частности, строк INI-файлов (см. гл. 6). Для удобной работы со строками такой структуры в классе TStrings дополнительно имеются следующие свойства.

Управление элементами списка осуществляется с помощью следующих методов:

Свойства:

Методы:

События:

Ниже приводится фрагмент программы, демонстрирующий создание списка строк и манипулирование его элементами:

var
  Items: TStrings;
  I: Integer;
begin
  { Создание списка }
  Items := TStringList.Create;
  Items.Add('Туризм');
  Items.Add('Наука');
  Items.Insert(1, 'Бизнес');
  ...
  { Работа со списком }
  for I := 0 to Items.Count - 1 do
   Items[I] := Uppercase(Items [I]);
  ...
   { Удаление списка }
   Items.Free;
end;

КЛАССЫ ДЛЯ ПРЕДСТАВЛЕНИЯ ПОТОКА ДАННЫХ

В Delphi существует иерархия классов для хранения и последовательного ввода-вывода данных. Классы этой иерархии называются потоками. Потоки лучше всего представлять как файлы. Классы потоков обеспечивают различное физическое представление данных: файл на диске, раздел оперативной памяти, поле в таблице базы данных (см. табл. 1).

Таблица 1.

Класс Описание
TStream Абстрактный поток, от которого наследуются все остальные. Свойства и методы класса TStream образуют базовый интерфейс потоковых объектов.
THandleStream Поток, который хранит свои данные в файле. Для чтения-записи файла используется дескриптор (handle), поэтому поток называется дескрипторным. Дескриптор - это номер открытого файла в операционной системе. Его возвращают низкоуровневые функции создания и открытия файла.
TFileStream Поток, который хранит свои данные в файле. Отличается от ThandleStream тем, что сам открывает (создает) файл по имени, переданному в конструктор.
TMemoryStream Поток, который хранит свои данные в оперативной памяти. Моделирует работу с файлом. Используется для хранения промежуточных результатов, когда файловый поток не подходит из-за низкой скорости передачи данных.
TResourceStream Поток, обеспечивающий доступ к ресурсам в Windows-приложении.
TBIobStream Обеспечивает последовательный доступ к большим полям таблиц в базах данных.

Потоки широко применяются в библиотеке VCL и наверняка вам понадобятся. Поэтому ниже кратко перечислены их общие ключевые свойства и методы.

Общие свойства:

Общие методы:

Ниже приводится фрагмент программы, демонстрирующий создание файлового потока и запись в него строки:

var
  Stream: TStream;
  S: AnsiString;
  StrLen: Integer;
begin
  { Создание файлового потока }
  Stream := TFileStream.Create('Sample.Dat', fmCreate);
  ...
  { Запись в поток некоторой строки }
  StrLen := Length(S) * SizeOf(Char);
  Stream.Write (StrLen, SizeOf (Integer) ) ; { запись длины строки }
  Stream.Write (S, StrLen);              { запись символов строки }
  ...
  { Закрытие потока }
  Stream.Free;
end;

ИТОГИ

Теперь для вас нет секретов в мире ООП. Вы на достаточно серьезном уровне познакомились с объектами и их свойствами; узнали, как объекты создаются, используются и уничтожаются. Если не все удалось запомнить сразу - не беда. Возвращайтесь к материалам главы по мере решения стоящих перед вами задач, и работа с объектами станет простой, естественной и даже приятной. Когда вы добьетесь понимания того, как работает один объект, то автоматически поймете, как работают все остальные. Теперь мы рассмотрим то, с чем вы встретитесь очень скоро - ошибки программирования.

Previous page:
Наследование
Top:
DRKB
Next page:
Свойства объектов