- •Основы офисного программирования и язык vba
- •Офисное программирование
- •Состав Office 2000
- •Инсталляция Office 2000
- •Содержимое диска "Resource Kit"
- •Документ Issues
- •Документ ork9
- •Папка Tools
- •Содержимое диска "Language Pack"
- •Об этой книге и ...
- •Моя благодарность
- •Vba и объекты. Обзор
- •Библиотека объектов Office 2000 - каркас приложений
- •Встраивание вместо наследования
- •Построение каркаса документа
- •Библиотека объектов Office 2000 и Object Browser
- •Объекты Application
- •Свойства-участники
- •Вторая группа терминальных свойств
- •Методы объектов Application
- •События объектов Application
- •Совместная работа приложений. Создание объектов Application. Раннее и позднее связывание
- •Коллекции в Office 2000
- •Коллекции объектов Office 2000
- •Коллекции Excel: Workbooks, Sheets
- •Коллекция Workbooks
- •Коллекция Sheets
- •Коллекции Word: Documents, Paragraphs и другие
- •Коллекция Documents
- •Коллекция Paragraphs
- •Коллекция Sections
- •Коллекции Characters, Words, Sentences
- •Коллекции и конструкция For Each … Next
- •Объекты Range
- •Что определяет объект Range?
- •Метод Range
- •Объекты Selection
- •Метод Select и свойство Selection
- •Активные объекты и метод Activate
- •Проектирование документов
- •Документ и его программный проект
- •Модули - обработчики событий
- •Стандартные модули
- •Модули классов
- •Модуль макросов
- •Структура модуля. Окно проекта и Окно кода
- •Окно проекта
- •Свойства проекта
- •Имя проекта
- •Защита проекта
- •Окно кода
- •Еще раз о "переиспользовании" модулей
- •Проект и область видимости
- •Система документов и ее проект
- •Организация системы документов
- •Как организуются ссылки между проектами
- •Обмен информацией между документами
- •Система документов One - Two - Three
- •Типы данных
- •Простые типы данных.
- •Объявление переменных и констант простых типов
- •Синтаксис объявления простых переменных
- •Объявления по умолчанию
- •Константы
- •Массивы
- •Динамические массивы
- •Записи и тип, определенный программистом
- •Что можно делать с записями?
- •Раздел объявлений
- •Раздел опций
- •Разделы констант, типов и переменных
- •Раздел Declare
- •Правила именования
- •Типы и классы Еще раз о понятии "класс"
- •Что нового в классах "Office 2000"
- •Создание класса "Личность"
- •Объекты и переменные
- •Объекты, класс которых определен пользователем.
- •Объекты "родного" приложения
- •ActiveX-объекты
- •Модуль класса Свойства
- •Сокрытие свойств
- •Конструкторы и деструкторы. Стандартные события
- •Стандартные события Initialize и Terminate
- •Два конструктора класса Rational
- •Процедуры - свойства
- •Как создаются процедуры- свойства
- •Синтаксис Let, Get и Set
- •Классы, как упаковка
- •Семейство классов и процедуры - свойства
- •Friend методы
- •События
- •Классы, объекты With Events и обработчики событий
- •Модуль класса с объектом WithEvents
- •Объект WithEvents
- •События собственных классов
- •Как создать класс с событиями
- •Как зажигаются события
- •Где и как следует создавать обработчики событий для экземпляров класса
- •Связывание объектов
- •Реальные объекты и инициирование событий
- •Семейство классов и реализация интерфейсов
- •Наследование
- •Виртуальные методы и полиморфизм
- •Абстрактные классы
- •Наследование и полиморфизм в Office 2000
- •Наследование интерфейсов
- •Полиморфизм семейства классов
- •Проект "Люди и Машины"
Проект "Люди и Машины"
Проектирование семейства классов, как правило, начинают с проектирования схемы, задающей иерархию и связи в семействе, определения прародителей, определяющих базовые свойства и поведение. Приведем в качестве примера семейство классов, объектами которого будут Люди и машины. Вот одна из возможных схем, определяющая классы этого семейства и отношения между ними.
Рис. 5.3. Схема семейства классов "Люди и Машины"
Мы не станем давать полную реализацию этой схемы. Для наших целей достаточно ограничиться ее частичной реализацией, где будут два родителя, имеющие общего потомка. У нас уже построен класс Личность, - пусть он и будет одним из родительских классов. Другим базовым родительским классом пусть будет класс Машина, задающий машины. Потомком этих двух родительских классов будет класс ВладелецМашины. Он наследует интерфейсы класса Личность и класса Машина. Поэтому объекты этого класса смогут входить и обрабатываться в разных группах, - в группе личностей и в группе машин. В нашем примере родительские классы не будут абстрактными. Напомним, что определенный в предыдущей лекции класс Личность является классом с событиями, так что его объекты могут реагировать на некоторые события, происходящие с ними. Мы не будем повторять здесь его описание. Класс Машина будет достаточно простым. Вот его определение:
Option Explicit
'Класс Машина
'Свойства класса
Private Марка As String
Private ДатаВыпуска As Date
Private Цвет As String
'Конструкторы класса
Private Sub Class_Initialize()
Марка = "Форд"
ДатаВыпуска = "20.07.1925"
Цвет = "Вишневый"
End Sub
Public Sub НоваяМашина(M As String, D As Date, C As String)
Марка = M
ДатаВыпуска = D
Цвет = C
End Sub
'Методы класса
Public Sub PrintDataCar()
Debug.Print "Марка = ", Марка
Debug.Print "ДатаВыпуска = ", ДатаВыпуска
Debug.Print "Цвет = ", Цвет
End Sub
Public Property Get МаркаМашины() As String
МаркаМашины = Марка
End Property
Public Property Get ЦветМашины() As String
ЦветМашины = Цвет
End Property
Public Property Get ДатаВыпускаМашины() As Date
ДатаВыпускаМашины = ДатаВыпуска
End Property
Пример 5.4. (html, txt)
У класса Машина имеется:
-
три закрытых свойства, обладающие статусом Read only,
-
два конструктора, - закрытый конструктор по умолчанию и открытый конструктор НоваяМашина,
-
один типичный для классов открытый метод, задающий печать свойств - PrintDataCar
Интерфейс класса составляют два открытых метода, они и будут наследоваться классом - потомком. Класс - потомок ВладелецМашины значительно больше унаследует от своего другого родителя - класса Личность. Вот определение класса ВладелецМашины:
Option Explicit
'Класс ВладелецМашины
'Наследует интерфейсы классов Личность и Машина
Implements Машина
Implements Личность
'Свойства класса
Private Сам As Личность
Private ЕгоМашина As Машина
Private Sub Class_Initialize()
Set Сам = New Личность
Set ЕгоМашина = New Машина
End Sub
'Реализация интерфейсов класса Личность
Private Sub Личность_CopyPerson(You As Личность)
Сам.CopyPerson (You)
End Sub
Private Sub Личность_InitPerson(ByVal FN As String, ByVal LN As String, ByVal DoB As Date)
'Инициализация личности
Сам.InitPerson FN, LN, DoB
End Sub
Private Sub Личность_PrintPerson()
'Печать в отладочном окне Immediate
Сам.PrintPerson
End Sub
Private Sub Личность_SayWhoIs()
' Вывод сообщения о поле и возрасте владельца машины
Dim StrMsg As String
StrMsg = "Думаю, Владелец машины марки: " & _
ЕгоМашина.МаркаМашины & " это - "
If Сам.WhoIs Then
If Year(Сам.ВашаДатаРождения) > 1967 Then
StrMsg = StrMsg & "молодая девушка!"
Else: StrMsg = StrMsg & "женщина!"
End If
Else
If Year(Сам.ВашаДатаРождения) > 1967 Then
StrMsg = StrMsg & "молодой человек!"
Else: StrMsg = StrMsg & "мужчина!"
End If
End If
MsgBox (StrMsg)
End Sub
Private Function Личность_WhoIs() As Boolean
Сам.WhoIs
End Function
Private Property Let Личность_ВашаДатаРождения(ByVal NewValue As Date)
Сам.ВашаДатаРождения = NewValue
End Property
Private Property Get Личность_ВашаДатаРождения() As Date
'Зажигает событие ДеньРождения
'в зависимости от значения текущей даты
Личность_ВашаДатаРождения = Сам.ВашаДатаРождения
End Property
Private Property Let Личность_ВашаФамилия(ByVal NewValue As String)
'Зажигает событие ИзменениеФамилии
Сам.ВашаФамилия = NewValue
End Property
Private Property Get Личность_ВашаФамилия() As String
Личность_ВашаФамилия = Сам.ВашаФамилия
End Property
Private Property Let Личность_ВашеИмя(ByVal NewValue As String)
Сам.ВашеИмя = NewValue
End Property
Private Property Get Личность_ВашеИмя() As String
Личность_ВашеИмя = Сам.ВашеИмя
End Property
Private Property Let Личность_ВашеОтчество(ByVal NewValue As String)
Сам.ВашеОтчество = NewValue
End Property
Private Property Get Личность_ВашеОтчество() As String
Личность_ВашеОтчество = Сам.ВашеОтчество
End Property
'Реализация интерфейсов класса Машина
Private Property Get Машина_ДатаВыпускаМашины() As Date
Машина_ДатаВыпускаМашины = ЕгоМашина.ДатаВыпускаМашины
End Property
Private Property Get Машина_МаркаМашины() As String
Машина_МаркаМашины = ЕгоМашина.МаркаМашины
End Property
Private Property Get Машина_ЦветМашины() As String
Машина_ЦветМашины = ЕгоМашина.ЦветМашины
End Property
Private Sub Машина_PrintDataCar()
ЕгоМашина.PrintDataCar
End Sub
Private Sub Машина_НоваяМашина(M As String, D As Date, C As String)
ЕгоМашина.НоваяМашина M, D, C
End Sub
'Собственный интерфейс класса ВладелецМашины
'Public методы - интерфейс Владельца машины
Public Sub InitCarOwner(FN As String, LN As String, DoB As Date, _
Marka As String, DB As Date, Color As String)
'Инициализация данных о хозяине и его машине
Личность_InitPerson FN, LN, DoB
Машина_НоваяМашина Marka, DB, Color
End Sub
Public Sub ConnectOwnerAndCar(pers As Личность, car As Машина)
'соединяет данные о хозяине и его новой машине
Сам.CopyPerson pers
Машина_НоваяМашина car.МаркаМашины, car.ДатаВыпускаМашины, _
car.ЦветМашины
End Sub
Public Sub PrintOwnerData()
Личность_PrintPerson
Debug.Print " владеет машиной: "
Машина_PrintDataCar
End Sub
Пример 5.5. (html, txt)
Прокомментируем этот довольно длинный текст. Вот на какие моменты следует обратить внимание:
-
Для того, чтобы реализовать полноценное наследование свойств и поведения родителей, а не только наследование интерфейсов, используется встраивание, - в классе определены свойства Сам класса Личность и свойство ЕгоМашина класса Машина.
-
В конструкторе по умолчанию Class_Initialize, вызываемом при создании объекта класса ВладелецМашины, объекты Сам и ЕгоМашина инициализируются, - будут вызваны их конструкторы по умолчанию класса Личность и класса Машина.
-
При наследовании интерфейсов класса Личность почти для всех методов наследовалось поведение родительского класса. Реализуется это достаточно просто - вызывается соответствующий метод объекта Сам.
-
Для метода SayWhoIs поведение переопределено. В данном случае при вызове метод учитывает специфику класса и сообщает некоторые данные, как о владельце, так и о его машине. Так что при вызове этого метода у просто личностей и у личностей, являющихся владельцами машин, результат будет различным.
-
Поскольку родительский класс допускает события, то и у потомка при вызове методов зажигаются соответствующие события.
-
Интерфейс класса Машина реализуется подобным образом. Полностью наследуется поведение родительского класса.
-
Собственный интерфейс класса довольно прост. У объектов этого класса нет новых дополнительных свойств, - все спрятано в свойствах встроенных объектов Сам и ЕгоМашина. Интерфейс составляют два конструктора и метод, осуществляющий печать данных. Обратите внимание, один конструктор InitCarOwner позволяет сконструировать новый объект класса по терминальным данным, характеризующим личность и его машину. Второй конструктор ConnectOwnerAndCar в качестве параметров использует ранее созданные объекты классов Личность и Машина, соединяя эти два объекта в один объект класса ВладелецМашины.