Классы и объекты


Давайте подведем предварительные итоги. Во-первых, мы рассмотрели, что такое встроенные типы данных, какие они бывают, в чем состоит их различие, как создавать переменные этих типов и т. д. Во-вторых, мы научились создавать собственные типы данных (записи), а также пользовательские процедуры и функции. Это уже достаточно весомый багаж знаний, однако остался еще небольшой, но очень важный раздел, посвященный таким понятиям объектно-ориентированного программирования, как классы и объекты (экземпляры классов).
В самом упрощенном понимании объект — это какая-то вещь или материальная сущность реального мира. Оглянитесь вокруг, и вы увидите, что наш мир состоит из бесконечного числа объектов: стол, машина, клавиатура компьютера, дом, человек и т. д. (более того, даже мир — это объект). Если приглядеться, то каждый объект имеет свойства (машина черного цвета) и операции, которые выполняются над этими свойствами (ту же машину можно перекрасить в экзотический металлик). Почти аналогично обстоит дело с объектами в абстрактном мире программ. Например, в качестве объекта можно рассматривать файл, в качестве свойства — его размер или имя, а в качестве операций — чтение или запись.
Рассмотрим еще один пример объекта в абстрактном мире программ — переменную author типа Person CO свойствами name И birthday. Итак, естЬ объект и есть свойства, что же является операцией в данном случае? Любая пользовательская процедура или функция, изменяющая свойства объекта author или просто работающая с ними. Например, процедура инициализации полей записи или процедура вывода на экран значений полей.
А теперь представьте, что код программы испещрен как процедурами, которые относятся к работе с записью author, так и функциями, относящимися к другим переменным, которых тоже не мало. Совсем нетрудно будет заблу диться в подобном хаосе и применять нужную функцию к неверным данным или, наоборот, необходимые данные подставлять не в ту функцию. Возникает естественное желание объединить данные и способы их обработки в одно целое — так, чтобы было ясно, какие процедуры предназначены для обработки каких данных. Таким образом, мы вплотную подошли к центральным понятиям объектно-ориентированного программирования — понятиям инкапсуляции и класса.
Объектно-ориентированное программирование (ООП) — наиболее популярная в настоящее время методология программирования, являющаяся развитием структурного программирования. Центральной идеей ООП является инкапсуляция, т. е. структурирование программы на модули особого вида, объединяющие данные и процедуры их обработки (вот оно, решение всех проблем!), причем внутренние данные модуля могут быть обработаны только предусмотренными для этого процедурами. В разных вариациях ООП этот модуль называют по-разному: класс, абстрактный тип данных, кластер и др. В VBA принято называть этот модуль модулем класса, или просто классом. Каждый такой класс имеет внутреннюю часть, называемую реализацией, и внешнюю — интерфейс.
Класс, таким образом, представляет собой новый тип данных, позволяющий создавать новые переменные этого типа (объекты) (иногда их еще называют экземплярами класса) и вести связанные с ними процедуры и функции. Программист описывает класс как сложный структурированный тип, состоящий из элементов, которые могут быть как собственно данными, т. е. значениями определенного типа данных, так и функциями, реализующими операции над элементами-данными. Элементы-данные называются свойствами класса, элементы-функции — методами класса. Такое описание служит шаблоном для создания в программе конкретных экземпляров (объектов) данного класса, имеющих свои конкретные имена.
В случае с записью Person при добавлении к ней двух процедур (persinit, persPrint) мы фактически получили класс, одним из объектов которого будет author. Доступ к свойствам и методам объекта осуществляется (как и в случае с записью) посредством точечной нотации. Например, для того, чтобы вывести на экран свойства объекта author с помощью метода Print, необходимо ввести в программу выражение author. Print ().
Помимо инкапсуляции, ООП VBA характеризуется еще одним немаловажным свойством — встраиванием. Встраивание — это механизм порождения новых классов с использованием существующих.
Пусть построен класс А, тогда при объявлении нового класса В его свойствами могут быть объекты класса А. В этом случае говорят, что класс А встроен в класс В, и класс А является родителем, а класс В — потомком. Встраивание — транзитивное отношение, т. е. можно создать произвольно длинную цепочку вложенных объектов, образующих иерархию родителей и потомков. Так, в новый класс С можно встроить объект класса В, который является объектом класса А.
Для приложений Office XP характерна ситуация, когда необходимо указать шесть-восемь уровней вложенности, чтобы добраться до нужного объекта. Например, чтобы скрыть панель инструментов Стандартная, выполните следующий оператор присваивания:
Outlook.Application.ActiveExplorer.ShowPane (olOutlookBar ,True )
Механизм встраивания очень удобен и естественен. Прародитель семейства классов может задавать некоторые фундаментальные свойства и методы, а многочисленные потомки, имея родительские корни (свойства и методы), привносят собственные узкоспециальные свойства и методы.
Например, создавая класс Book со свойством Author класса Person, мы не только используем фундаментальные свойства и методы класса Person, но и вводим собственные свойства (title) и методы.
Наряду со встраиванием, существует еще один способ использования существующих классов при создании новых, он называется наследование. При наследовании указывается, что вновь создаваемый класс В на основе класса А содержит все (или некоторые) методы и свойства класса А, а также свои собственные методы и свойства. Например, на основе класса Person можно определить класс Author, который содержит все методы и свойства класса Person, а также свои собственные, например список книг данного автора.
Перейдем теперь от теоретического описания канонов ООП к практике их применения в VBA и начнем с синтаксиса. Синтаксически классы в VBA оформляются в виде специальных модулей классов (имя класса — это имя модуля), где в разделе Declarations помещается описание свойств (переменных) класса, а дальше идет описание методов (процедур) класса. Синтаксически описания свойств и методов практически не отличаются от описания обыкновенных переменных и процедур. Случаи отличия или особенностей употребления будут оговорены отдельно.
Давайте рассмотрим работу с классами на примере класса Person.
Создание класса Person
> Insert > Class Module
Properties Name:= Person
Создание класса
Public name As String Private birthday As Date Private male As Boolean
Public Sub perslnit( Optional persName As String = "Novikov", Optional persBirth As Date = #10/10/511, Optional persMale As Boolean = True)
name = persName birthday = persBirth male = persMale End Sub
Public Sub persPrint ()
Dim str As String
str = "Person name is " & name & Chr(13) & Ilf(male,"He","She") & " was born in " & birthday
MsgBox(str) End Sub
Перед тем как перейти к описанию синтаксиса объявления объектов класса, мы хотели бы обратить внимание на внутренний процесс их создания. Вообще, объект — это переменная, поэтому, когда он создается, для него выделяется необходимая память (ее размер зависит от типов свойств класса), а имя объекта ссылается на адрес памяти, где расположен объект. А теперь небольшой фокус, невозможный для переменных простых типов. В VBA есть возможность создания только ссылки на объект без фактического его присутствия. Подобная ссылка указывает адрес памяти, где будет храниться объект. Синтаксис объявления ссылок на объект не отличается от объявления простых переменных:
{Dim | Private | Public} имяОбъектаAs Object
Если вы обратитесь к таблице встроенных типов (), то увидите, что для переменных данного типа отводится 4 байта, ровно столько, сколько необходимо для хранения адреса памяти. Конечно, ссылка сама по себе бессмысленна и ее, в конце концов, необходимо будет связать с реально существующим объектом посредством оператора присваивания set, но до этого нужно объявить объект. Синтаксис объявления объектов, класс которых определен пользователем, прост:
(Dim |Private | Public | Static} имяОбъекта As [New] имяКласса
Спецификатор New указывает компилятору, что создается новый объект и под него необходимо выделить память. Использование оператора set позволяет связывать ссылку с реальным объектом:
Set ИмяОбъекта = {[New] объектноеВыраженме | Nothing}
имяОбъекта и объктноевыражение — это ссылки на объект. Таким образом, ссылке слева присваивается значение ссылки справа. Спецификатор Nothing разрывает установленное значение ссылки. Связывание с использованием оператора New называется ранним, с использованием ссылок на объект — поздним.
Рассмотрим объявление объектов класса Person. Сначала создается объект author. Далее посредством метода класса persinit инициализируются свойства объекта: имя, дата рождения и пол. После чего объявляется ссылка на объект, а потом происходит присваивание ссылке he значения ссылки author и в качестве подтверждения того, что все связалось верно, производится вывод свойств объекта he посредством метода persPrint.
Объявление объектов класса, определенного пользователем
Sub ObjectExample () Dim author As New Person Dim he As Object
author.perslnit "Novikov", #10.10.51*
Set he = author

he.persPrint End Sub