Основы офисного программирования и язык VBA

         

Обертывание коллекции VBA


Обратите внимание, наш только что приведенный пример ВводСписка, иллюстрирующий часто возникающую на практике задачу, невозможно реализовать, используя встроенный класс Collection.Причина этого уже пояснялась, - коллекция хранит ссылки на созданные вне нее элементы, она не обладает собственной памятью. Поэтому пользователь сам должен заботиться о создании и хранении элементов. Конечно, хотелось бы поручить эту задачу самой коллекции, как это делается в созданном динамическом классе СписокЛичностей. С другой стороны этот класс имеет значительно менее мощные методы AddFirst и AddLast в сравнении с методом Add класса Collection. Класс СписокЛичностей не позволяет создавать словари, он значительно менее эффективен, чем класс Collection в тех случаях, когда требуется обеспечить прямой доступ к элементам списка. Возникает вопрос, нельзя ли соединить достоинства двух подходов? Оказывается, можно. Для этого применяется стандартная при работе с классами технология обертывания. Суть ее в том, что стандартный объект, например, элемент управления встраивается в собственный класс. Методы класса могут вызывать методы объекта, сохраняя тем самым мощь стандартного объекта. С другой стороны можно добавить новые методы или расширить функциональность существующих. Мы продемонстрируем эту технологию, показав как можно строить собственные коллекции для объектов любого класса. Конечно, нам не удастся построить универсальный класс, расширяющий возможности класса Collection, но нам удастся показать, что для каждого собственного класса элементов, можно построить коллекцию, обладающую всеми свойствами обычной коллекции, но, вместе с тем, хранящую элементы в самой коллекции.

Не будем изобретать новых примеров и построим класс КоллекцияЛичностей. Этот класс будет обладать всеми стандартными свойствами и методами класса Collection, дополненными методами класса СписокЛичностей. Он будет иметь:

  1. Свойство Count - возвращает число элементов коллекции. Доступно только для чтения, имеет тип возвращаемого значения Long.
  2. Метод AddPerson (item, key, before, after) - добавляет элементы в коллекцию.
    Первый параметр Item является обязательным и задает добавляемый элемент. Параметр key - необязателен, он задается, когда элементу ставится в соответствие ключ. Два последних необязательных параметра уточняют позицию вставки, - задают индекс или ключ элемента, перед или после которого добавляется новый элемент. Только один из этих параметров может быть задан. Если не задан ни один, элемент добавляется в конец коллекции. Заметьте, несмотря на внешнее сходство метод AddPerson отличается от метода Add класса Collection. Во-первых, параметр Item будет иметь строго фиксированный тип Личность. Во-вторых, есть различия в реализации. Коллекция будет хранить не ссылку на элемент Item класса Личность, а копию этого элемента.
  3. Метод Remove(key) - удаляет элементы коллекции. Удаляется элемент с заданным ключом: заметьте, это может быть индекс элемента. После удаления происходит перенумерация элементов и уменьшается счетчик Count.
  4. Метод Item(key) - возвращает значение элемента списка с заданным ключом. И здесь в роли ключа может выступать обычный индекс элемента.
  5. Метод PrintList() - печатает элементы списка в его текущем состоянии.
  6. Метод PrintHystory - печатает историю создания списка, - все его элементы, даже если они и были удалены впоследствии.


Наряду с открытыми свойствами и методами наш класс будет содержать и закрытые свойства и методы:

  1. Свойство First - указатель на начало списка, хранящего элементы коллекции.
  2. Событие Initialize - конструктор по умолчанию, инициализирует список.
  3. Метод AddFirst - создает копии элементов и добавляет их в список, представляющий внутреннюю память коллекции.


Вот полное описание класса КоллекцияЛичностей, обертывающего класс Collection. Класс сохранил все мощные свойства стандартной коллекции и, к тому же, приобрел новые привлекательные свойства:

Пример 5.11.

(html, txt)

Приведем комментарии к этому тексту:

  1. Прежде всего, следует обратить внимание на то, что объект Persons класса Collection встроен, как свойство, в создаваемый класс. Этот объект инициализируется конструктором по умолчанию, - обработчиком события Initialize в тот момент, когда создается сам объект класса КоллекцияЛичностей.

    Содержание раздела