Наверное каждый из читающих эту статью что-то коллекционирует или коллекционировал ранее, начиная с фантиков от конфет до автомобилей мировых звезд. Каждому свое. Коллекционирование не чуждо и Лису, (коллекции Controls в формах, Files в активном проекте и т.п.). К зрелости, а точнее к восьмой версии, Лис собрался и начал коллекционировать посредством отдельного класса, причем все подряд, что придет в голову программисту, тренирующего рыжего хищника.
Итак, с восьмой версии, программисту предоставлен новый класс - collection - коллекции. Класс, который не богат свойствами и методами, да и те не все представляют интерес для программиста. Что мы имеем?
Свойства(представляющие интерес для нас выделены красным):
- BaseClass
- Class
- ClassLibrary
- Comment
- Count
- KeySort
- Name
- Parent
- ParentClass
- Tag
... методы (представляющие интерес для нас выделены красным):
- Add
- AddProperty
- GetKey
- Item
- ReadExpression
- ReadMethod
- Remove
- ResetToDefault
- SaveAsClass
- WriteExpression
- WriteMethod
... и события:
- Destroy
- Error
- Init
Почитаем, что говорится о коллекциях в руководстве по языку.
Вы можете использовать коллекции для группировки связанных предметов, в качестве которых обычно выступают объекты, которые, в свою очередь, могут быть любого типа. Коллекции предоставляют механизм для работы с объектами, хранящимися в контейнерах и включают в себя стандартные пути доступа и прохода по объектам коллекции. Класс Collection работает как истинный контейнерный класс, несмотря на то, что среди его методов отсутствует AddObject, обычный, к примеру, для классов форм и страничных фреймов.
Класс Collection представляет собой базовый класс, который вы можете субклассировать в файлах программ и библиотек классов.
цитирую еще раз "среди его методов отсутствует AddObject". Ох, уж это руководство. После такой фразы невольно возникает вопрос - а как заполнить коллекцию? Нет чтобы написать: "класс Collection работает как истинный контейнерный класс, в котором для заполнения коллекции объектами используется метод Add, отличающийся по поведению от традиционного метода AddObject, обычного, к примеру, для классов форм и страничных фреймов".
Пожалуй с этого метода мы и начнем разбираться с этим классом.
Создать коллекцию так же просто, как и любой другой класс. Напечатаем в командном окне приведенную ниже строку:
oCollection=CREATEOBJECT("Collection")
Что можно добавить в коллекцию? Как сказано в руководстве - "объект - член коллекции - может быть любого действительного типа, который можно присвоить переменной памяти. Это включает в себя простые типы данных, такие как строки, числа, даты, логические значения (интересно, а какой смысл вводить в коллекцию логические значения? Правда это можно использовать достаточно своеобразно, но об этом позже) или более сложные типы, так как объекты Visual FoxPro и объекты Component Object Model (COM).
Добавим две строки в наш объект. Для этого необходимо использовать метод Add, чей синтаксис прост и содержит три параметра:
Collection.Add( eItem [, cKey [, [eBefore |, eAfter ]]] )
Я специально выделил второй параметр красным цветом. Объект - член коллекции - может иметь ключ. Но! Либо вы используете ключи со всеми вводимым в коллекцию объектами, либо ни с одним из них!
Итак исполним предложенное:
oCollection.Add( "String that I suffer out before lunch","String1")
oCollection.Add( "String that I wrote with a great trouble after lunch","String2")
Поскольку ключи могут быть использованы для обращения к объекту-члену коллекции, то стало быть они должны быть уникальными. Если вы попытаетесь использовать в качестве ключа выражение, уже имеющееся в коллекции, то вы неизбежно получите сообщение об ошибке Error 2062 - The specified Key already exists (Указанный ключ уже существует)
Коллекция создана и в ней хранится два объекта - две строки. Как к ним обратиться? Очень просто! Можно использовать введенные одновременно с объектом ключи, а можно использовать целочисленный индекс, автоматически создающийся при вводе объекта в коллекцию. То есть, два приведенных ниже выражения равнозначны по сути.
? oCollection.Item("String1")
? oCollection.Item(1)
Как удалить объект из коллекции? Также очень просто! Если нужно удалить конкретный объект, то в методе Remove указываем либо его ключ, либо его индекс. Если же мы хотим очистить всю коллекцию одним махом - то нужно вызвать метод Remove, которому в качестве параметра передать -1 (минус единицу)
? oCollection.Remove("String1")
? oCollection.Remove("String2")
? oCollection.Count
Последняя строка вернет ноль - 0. А что произойдет, если мы воспользуется третьим параметром. Поскольку наша тестовая коллекция в данный момент пуста, заполним ее следующим образом:
oCollection.Add(1,"N1")
oCollection.Add(2,"N2")
oCollection.Add(3,"N3","N1")
oCollection.Add(4,"N4",,"N1")
Что мы сделали? Первая и вторая строки кода добавляют два числа в коллекцию, третья строка кода вставляет объект, имеющий ключ "N3" в коллекцию перед объектом-членом коллекции, чей ключ имеет выражение "N1", а четвертая строка вставляет объект, имеющий ключ "N4" после объекта-члена коллекции "N1", что сделано с помощью двух запятых в синтаксисе вызова метода. Посмотрим теперь содержание коллекции, используя целочисленные индексы:
? oCollection.Item(1)
? oCollection.Item(2)
? oCollection.Item(3)
? oCollection.Item(4)
В результате мы получим значения 3,1,4,2. То есть при вводе с использованием опции eBefore | eAfter индексы коллекции перестраиваются, что необходимо учитывать, при их использовании. Но спасательная веревка все-таки существует, поскольку у класса коллекции имеется метод GetKey, который может быть использован для проверки - а к нужному ли объекту мы обращаемся. Однако, метод будет работать только при наличии введенных для каждого объекта-члена коллекции ключей.
Естественно возникает вопрос - а можно ли использовать третий параметр, в случае, если не используются ключи? Что написано по этому поводу в руководстве? "Inserting a new item into a collection before or after an existing one requires that the collection must be a keyed collection" - Вставка нового объекта в коллекцию до или после существующего объекта-члена коллекции требует, чтобы коллекция была создана с использованием ключей. Так ли это? Попробуем вставить объекты в коллекцию с использованием третьего параметра метода Add, предполагая, что в его качестве будут использованы индексы:
* очистим объект коллекции, созданный в предыдущем примере
oCollection.Remove(-1)
oCollection.Add(1)
oCollection.Add(2)
oCollection.Add(3,,1)
oCollection.Add(4,,,1)
? oCollection.Item(1)
? oCollection.Item(2)
? oCollection.Item(3)
? oCollection.Item(4)
Итак, что мы сделали. Для начала мы удалили из коллекции все объекты-члены. Следующие две строки добавили два члена коллекции, которым автоматически были присвоены индексы 1 и 2 соответственно. Третья строка должна ввести объект в коллекцию перед объектом-членом коллекции, чей индекс равен 1. И четвертая строка должна ввести объект в коллекцию после объекта-члена коллекции, чей индекс равен 1. В итоге мы получили 3,4,1,2. Получается, что использование индексов вместо ключей, возможно. Однако, приведенный пример имел одну неопределенность, которая состояла в том, что в качестве объектов использовались целые числа, того же порядка, что и индексы. Проверим, использовались ли индексы коллекции при вызове метода Add, если в качестве объектов вводились символьные значения. Для этого исполним приведенный ниже пример:
oCollection.Remove(-1)
oCollection.Add("A")
oCollection.Add("B")
oCollection.Add("C",,1)
oCollection.Add("D",,,1)
? oCollection.Item(1)
? oCollection.Item(2)
? oCollection.Item(3)
? oCollection.Item(4)
В итоге мы получим в качестве результата C,D,A,B, что подтверждает предположение о возможности использовании индексов в качестве третьего параметра метода Add. Ну хорошо, а что если использовать в качестве третьего параметра ссылку на объект коллекции?. То есть oCollection.Item(n)? Вызов метода возвращает непосредственно объект-член коллекции. Стало быть в чистом виде мы его не можем использовать для организации коллекции с указанием места вставки нового объекта. Хотя это вполне реально сделать в субклассе коллекции, основаном на базовом классе коллекции Visual FoxPro. Но об этом в одной из следующих частей.
|