- •Основы офисного программирования и язык 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
- •Наследование интерфейсов
- •Полиморфизм семейства классов
- •Проект "Люди и Машины"
Виртуальные методы и полиморфизм
Как взаимодействуют между собой объекты разных классов, связанных отношением наследования? Возможны ли взаимные присваивания между объектами родительских классов и их потомками? Ответ на второй вопрос положителен лишь "наполовину". Совместимость по присваиванию обеспечивается лишь в одну сторону - от родителей к потомкам: объекту родительского класса может быть присвоено значение объекта-потомка - обратное недопустимо. Это и понятно: ведь потомок, сохраняя все свойства родителя, может иметь и другие свойства.
Присваивание объекта объекту производится редко. Важнее, что совместимость по присваиванию имеет место в следующих случаях:
-
совместимость между формальным и фактическим параметром процедуры или функции. Формальный параметр может иметь тип базового класса, а фактический параметр - аргумент - при вызове функции может быть объектом любого производного класса.
-
совместимость указателей. Указатель может ссылаться на базовый класс, но при конструировании объекта в операторе "new" может быть вызван конструктор производного класса, что позволяет создать объект соответствующего класса. В более общей ситуации указателю базового класса может быть присвоен указатель производного класса.
Ниже мы покажем, что свойство совместимости по присваиванию в сочетании с возможностью определения виртуальных методов приводит к весьма полезным следствиям.
Семейство классов может иметь виртуальные методы. Если какой-то метод базового класса объявлен как виртуальный с атрибутом virtual, эта характеристика сохраняется для всех классов-потомков. В случае переопределения в производном классе виртуального метода должно сохраняться число параметров метода и их типы, что гарантирует одинаковую форму вызова виртуального метода как производного, так и базового класса.
Когда создается объект, в классе которого определены виртуальные методы, конструктор класса для этого объекта заносит строку в таблицу виртуальных методов. В ней содержатся ссылки на расположение виртуальных методов данного класса на этапе выполнения приложения, что позволяет реализовать механизм "позднего связывания" и при вызове объектом своего виртуального метода динамически найти по таблице и вызвать нужный метод.
Виртуальность обеспечивает возможность написания полиморфной функции, в теле которой вызываются виртуальные методы.
Принципиально виртуальный метод от не виртуального отличается механизмом позднего связывания , применяемым для организации вызова виртуального метода. Во многих языках программирования методы могут быть как виртуальными, так и, в большинстве случаев, не виртуальными. В языке VBA это не так, здесь практически все методы виртуальные и для них применяется механизм позднего связывания. Это и понятно, поскольку VBA по существу интерпретируемый язык, а интерпретация подразумевает позднее связывание. Поэтому, чтобы Вы почувствовали разницу между виртуальными и не виртуальными методами, позвольте привести один пример на языке Visual C++. Рассмотрим следующий пример. Пусть имеются базовый класс Base и производный от него класс Derived, в которых определены виртуальный метод VirtMethod и невиртуальный метод NonVirtMethod. В базовом классе определена также полиморфная функция Test:
class Base
{
public:
virtual void VirtMethod (); // печатает слово" Отец"
void NonVirtMethod (); // печатает слово" Мать"
void Test ()
{
VirtMethod (); // вызов виртуального метода
NonVirtMethod (); // вызов не виртуального метода
}
}
class Derived: public Base
{
public:
virtual void VirtMethod (); // печатает слово" Сын"
void NonVirtMethod (); // печатает слово" Дочь"
}
Когда компилятор в базовом классе Base создает код для функции Test, то, анализируя вызов не виртуального метода NonVirtMethod(), он уже на этапе компиляции создаст обращение к методу NonVirtMethod класса Base.
Совсем иначе он поступит, анализируя вызов виртуального метода VirtMethod. Для виртуального метода на этапе компиляции нельзя определить, метод какого класса следует вызывать. Это может быть метод класса Base или класса Derived. Возможно даже, что уже после того, как функция Test будет откомпилирована, программист определит новый класс - потомок класса Derived со своим виртуальным методом VirtMethod.
Решение о том, метод какого класса следует вызывать, откладывается до момента вызова функции Test. Решение принимается не на этапе компиляции, а на этапе выполнения программы. В момент вызова виртуального метода, используя таблицу виртуальных методов, выполняется необходимое связывание и вызывается требуемый метод соответствующего класса. Закончим наш пример объявлением объектов базового и производного классов и вызовами функции Test с этими объектами в качестве фактических параметров:
// При создании объекта BaseItem вызывается конструктор класса Base.
Base BaseItem;
// При создании объекта DerivedItem вызывается конструктор класса Derived
Derived DerivedItem;
// Вызов функции Test
BaseItem.Test(); // Будет напечатано "Отец" и "Мать"
DerivedItem.Test(); // Будет напечатано "Сын" и "Мать".
Функция Test является примером полиморфной функции. Заметьте: она имеет по умолчанию первым параметром указатель на объект базового класса (this). Продолжим рассмотрение нашего примера и покажем, как указатели обеспечивают полиморфизм:
// Полиморфные указатели pItem1 и pItem2 ссылаются на базовый класс Base.
// Вызывается конструктор и создается динамический объект класса Base.
Base* pItem1 = new Base();
// Вызывается конструктор и создается динамический объект класса Derived
Base* pItem2 = new Derived();
// Будет вызван метод класса Base и напечатано слово "Отец".
pItem1 ->VirtMethod();
// Будет вызван метод класса Derived и напечатано слово "Сын".
pItem2 -> VirtMethod();
Теперь мы можем уточнить понятие полиморфизма семейства классов. Заметьте, что полиморфизм связан именно с семейством классов. Внутри одного класса могут существовать перегруженные методы, но не полиморфные. Виртуальный метод, определенный в базовом и производных классах с одним и тем же именем и одним и тем же набором параметров, но с разной реализацией, называется полиморфным. Такой метод существует во множестве форм. Функция, имеющая в качестве параметра объект базового класса и вызывающая виртуальные методы этого объекта, также называется полиморфной. Она работает по-разному в зависимости от того, какой объект передан ей в качестве фактического параметра. Полиморфным называется и указатель базового класса, вызывающий виртуальные методы. Полиморфизм такого указателя обеспечивается за счет того, что указатель может быть связан с объектом любого из производных классов. Семейство классов обладает свойством полиморфизма, если в нем реализованы полиморфные функции и полиморфные указатели.