Общие определения
Сначала определимся: что же такое объект в понимании объектно-ориентированного программирования. В самом простом (житейском) понимании объект — это какая-то вещь, и так же как и в окружающем мире, объект имеет свойства ("камень твердый") и операции, которые выполняются над этими свойствами (камень можно разбить). Почти так же обстоит дело и с объектами в мире программ. Например, в качестве объекта можно рассматривать файл, в качестве свойства — его размер или имя, а в качестве операций — чтение или запись. Итак, есть объект и есть свойства — что же является операцией? Любая пользовательская процедура или функция, изменяющая или просто работающая со свойствами объекта. Например, процедура инициализации полей записи или процедура вывода на экран значения полей. Возникает естественное желание объединить данные и способы их обработки в одно целое, так чтобы было ясно, какие процедуры предназначены для обработки определенных данных. Таким образом, мы вплотную подошли к центральным понятиям объектно-ориентированного программирования — понятиям инкапсуляции и класса.
Инкапсуляция и классы
Объектно-ориентированное программирование (далее ООП) - наиболее популярная в настоящее время методология программирования, являющаяся развитием структурного программирования. Центральной идеей ООП является инкапсуляция, т. е. структурирование программы на модули особого вида, объединяющие данные и процедуры их обработки, причем внутренние данные модуля могут быть обработаны только предусмотренными для этого процедурами. В VBA принято название модуль класса или просто класс. Каждый класс имеет внутреннюю часть, называемую реализацией, и внешнюю часть, называемую интерфейсом. Класс таким образом, представляет собой новый тип данных, позволяющий создавать новые переменные этого типа - объекты (иногда их еще называют экземплярами класса). Объект состоит из элементов, которые могут быть как собственно данными, т. е. значениями определенного типа данных, так и функциями, реализующими операции над элементами - данными. Элементы - данные называются свойствами класса, элементы - методами класса. Такое описание служит шаблоном для создания в программе конкретных экземпляров (объектов) данного класса, свои конкретные имена.
Встраивание
Помимо инкапсуляции, ООП на VBA характеризуется еще одним немаловажным свойством - встраиванием. Встраивание - это механизм порождения новых классов с использованием существующих. Пусть построен класс А, тогда при объявлении нового класса В его свойствами могут быть объекты класса А. В этом случае говорят, что класс А встроен в класс В, и класс А является родителем, а класс В - потомком. Встраивание - транзитивное отношение, т. е. можно создать произвольно длинную цепочку вложенных объектов, образующих иерархию родителей и потомков. Так, в новый класс С можно встроить объект класса В, который является объектом класса А. Для приложений Office XP характерна ситуация, когда необходимо указать 6 - 8 уровней вложенности, чтобы добраться до нужного объекта. Например, чтобы скрыть панель инструментов Стандартная в документе Word, необходимо выполнить следующее присваивание:
Word.Application.ActiveDocument.CommandBars(2).Visible = False
Механизм встраивания очень удобен и естественнен. Прародитель семейства классов может задавать некоторые фундаментальные свойства и методы, а многочисленные потомки, имея родительские корни (свойства и методы), привносят собственные узкоспециальные свойства и методы.
Наследование
Наряду со встраиванием, есть еще один способ использовать существующие классы при создании новых, он называется наследованием. При наследовании указывается, что вновь создаваемый на основе класса А класс В содержит все (или некоторые) методы и свойства класса А, а также свои собственные методы и свойства. Различие между встраиванием и наследованием только синтаксическое. При встраивании, используемом в VBA для ссылки на метод или свойство встроенного класса, мы используем имя поля этого класса. При наследовании (характерном для С и C++) имя свойства или метода родительского класса можно использовать непосредственно.
Создание класса
Синтаксически классы в VBA оформляются в виде специальных модулей классов (имя класса - это имя модуля), где в разделе Declarations помещается описание свойств (переменных) класса, а дальше идет описание методов (процедур) класса. Синтаксически описания свойств и методов практически не отличаются от описания обыкновенных переменных и процедур. Случаи отличия или особенностей употребления будут оговорены отдельно. Для создания модуля класса необходимо в окне базы данных выполнить следующие действия:
Insert - Class Module - "Имя класса"
Следует выбрать для класса такое имя, которое легко будет распознаваться, и отражать информацию о том, какие объекты описывает данный класс объектов.
Процедуры класса
В VBA все процедуры класса делятся на три группы:
- процедуры - методы
- процедуры - свойства
- процедуры - репликации на события
Процедуры - методы
Синтаксис объявления таких процедур не отличается от стандартного, за исключением использования ключевого слова Friend. Ключевое слово Friend, как и ключевые слова Private и Public, предназначено для ограничения области видимости метода. Если Private делает метод видимым только внутри модуля, a Public - для всех модулей всех проектов, то Friend занимает промежуточную позицию между ними: он делает видимым метод только в том проекте, где был описан класс.
Процедуры - свойства
Как известно, определение класса в VBA состоит из двух разделов:реализации и интерфейса. Одна из наиболее трудных задач для программистов - новичков в ООП заключается в определении того, какие члены класса делать закрытыми (включать в раздел реализации), а какие, наоборот, открытыми (включать в раздел интерфейса). Общим правилом можно считать то, что чем меньше пр��грамме известно о реализации класса, тем лучше, т. е. желательно скрыть посредством ключевого слова Private как можно большее количество свойств класса в раздел реализации, а доступ к свойствам осуществлять через специальные Public - методы, организующие интерфейс класса. Сокрытие информации (инкапсуляция) - это сокрытие деталей реализации функций, класса или даже программы. В условиях сокрытия информации программист работает с функциями и классами как с черными ящиками. Другими словами, передавая функции некоторое значение в форме входного параметра, программист знает лишь результат, который будет получен на выходе этой функции. Сокрытие информации в реализационную часть класса и доступ к ней через функциональный интерфейс повышает надежность программы. Имеется два способа создания свойств:
- Более простой из них заключается в создании в разделе описаний модуля класса переменной, объявленной с помощью ключевого слова Public. Таким образом, пользователи объекта получат возможность устанавливать и получать значение, сохраняемое в этой переменной. (Иными словами, свойство доступно как для чтения, так и для записи). Имя переменной определяется именем свойства, которое используется в вашей программе, поэтому, как и в случае имен классов, следует применять имена, отражающие содержимое переменных. Хотя использование общих переменных для определения свойств является самым простым способом, у него имеется несколько недостатков:
- У созданного класса нет никакой возможности определить, когда внешний процесс изменил значение свойства. Это может сыграть свою негативную роль в том случае, когда вам нужно ограничить значения определенным интервалом или выполнить какое - либо действие при изменении значения.
- Невозможно наложить ограничения на значения свойства или выполнить другую проверку данных. К примеру, вы можете захотеть ограничить значение свойства, представляющего возраст человека, положительными действительными числами.
- Невозможно создавать свойства, предназначенные только для чтения. В программах часто возникают ситуации, когда нужно возвратить значение свойства, не присваивая его, особенно в тех случаях, когда такие значения основаны на других данных.
- Для того чтобы справиться с этими недостатками, следует использовать второй способ создания свойства, а именно, создание свойства при помощи процедуры Property, их всего три: Property Let, Property Set, Property Get. Рассмотрим их подробнее:
Property Let - процедура записи, которая позволяет присваивать свойству новые значения
[{Public|Private|Friend}] [Static] Property Let имяПроцедурыСвойства ([списокПараметров] значение) [блокОператоров1] [Exit Property] [блокОператоров2] End Property
Синтаксис прост и понятен. Вначале идут операторы объявления видимости процедуры - свойства и необязательное ключевое слово Static. Кстати, хотя использование ключевого слова Private допустимо, его присутствие сводит на нет смысл процедуры - свойства.
имяПроцедурыСвойства - это имя процедуры, изменяющей свойство. Кстати, желательно, чтобы имя повторялось во всех трех процедурах-свойствах, если они имеют дело с одним и тем же свойством.
СписокПараметров - это список дополнительных параметров, участвующих в процедуре. Синтаксис списка параметров абсолютно такой же, как и у списка в обыкновенной процедуре. Обратите внимание на то, что все три процедуры-свойства, имеющие одно и то же имя, обязаны иметь одинаковый список параметров.
значение - это самый важный обязательный параметр, значение которого передается свойству.
Далее идет блокОператоров, в котором следует произвести присваивание значению свойства значения фактического параметра значение.
Property Set - процедура записи, которая позволяет присваивать свойству и свойству - ссылке новые значения. Отдельная процедура нужна, поскольку свойство - ссылка указывает на объект, а присваивание объектам отличается от присваивания переменным простых типов.
[{Public I Private|Friend}] [Static] Property Set имяПроцедурыСвойства ([списокПараметров] ссылкаНаОбъект) [блокОператоров1] [Exit Property] [блокОператоров2] End Property
Здесь только одно отличие от предыдущей процедуры: вместо параметра значение, стоит параметр ссылкаНаОбъект, который представляет имя ссылки на объект, присваиваемый свойству - ссылке.
Property Get - процедура чтения (а точнее, функция), которая позволяет считывать значение свойства. Эта процедура применима как к простым свойствам, так и к свойствам-ссылкам.
[{Public I Private|Friend}] [Static] Property Get имяПроцедурыСвойства ( [списокПараметров] ) As ТипДанных [ блокОператоров 1 ] [имяПроцедурыСвойства = выражение] [Exit Property] [ блокОператоров 2 ] End Property
Как видно, Property Get - это функция, и для нее действуют все синтаксические правила функций. Напомним лишь одно: тип значения, возвращаемого функцией, должен совпадать с типом значения выражение.
Создание экземпляра класса
Определив класс, задав ему несколько свойств и методов, можно использовать его в программе VBA. Но для этого сначала необходимо создать новый экземпляр класса. Невозможно просто ссылаться на переменные или вызывать процедуры модуля класса таким образом, как это делается в стандартном модуле: VBA выдаст ошибку компиляции "Подпроцедура или функция не найдена", так как возможности найти процедуру в глобальном пространстве имен не существует. Процедура останется "скрытой" до тех пор, пока вы не создадите новый экземпляр класса, и тогда можно вызвать ее только как метод созданного экземпляра класса. Для создания нового экземпляра класса нужно объявить объектную переменную, которая используется для хранения ссылки на созданный экземпляр класса. Для переменных, применяемых для ссылки на пользовательские классы, действуют те же правила, что и для переменных, ссылающихся на объекты VBA или приложения. Их можно описать, используя зарезервированные слова Dim, Private, Public и Global. Следующим шагом является создание нового экземпляра объекта и сохранения ссылки на него в переменной. Для этого используется оператор Set в сочетание с ключевым словом New.
Создание экземпляра класса. Имя класса User, имя экземпляра класса tmpuser.
Dim tmpuser As User Set tmpuser = New User
Заметьте, что типом данных в этом примере является имя класса, которое было определено раньше. Хотя такой синтаксис может показаться избыточным, для создания нового экземпляра объекта обязательно нужно использовать ключевое слово New в операторе Set. Если этого не сделать, то при попытке применить любое свойство или метод этого класса, VBA выдаст сообщение об ошибке выполнения 91 - "Не задана объектная переменная или переменная блока with". Для создания нового экземпляра объекта простого описания объектной переменной при помощи оператора Dim недостаточно.
Неявное создание экземпляра класса
Объявление переменной и создание нового экземпляра класса можно объединить в одном операторе. Вот как это будет выглядеть:
Dim tmpuser As New User
После такого объявления переменную можно сразу использовать, обращаясь к свойствам и методам объекта, на который она указывает. При этом сам объект создается не оператором Dim, а позднее, при первом обращении к переменной. Хотя описанный способ неявного создания объектов и удобен, поскольку позволяет сэкономить одну строку кода, он имеет один недостаток: из-за того что в сложном приложении вы не знаете точно, когда будет создан объект, отладка такого приложения может быть затруднена. Поэтому рекомендуется всегда создавать объект явно, с помощью отдельного оператора Set New.
|