Коллекции объектов

Алиса - экземпляр класса User, и в общем случае у объекта User может быть много полномочий. Иными словами, с Алисой должен быть ассоциирован список полномочий. В некоторых языках программирования для хранения списков применяются массивы, но в Dart нет специального типа Array, а есть интерфейсы Collection и List, причем List расширяет Collection. У интерфейса List имеется реализация по умолчанию, поэтому мы можем создавать его экземпляры с помощью ключевого слова new:

Collection permlssionsCollection = new List(); List permissionsList = new List();

Ключевое слово as

В некоторых случаях желательно рассматривать конкретную переменную как экземпляр другого типа. Классический случай: имеется переменная типа Collection, но записывается в нее список. Это допустимо, однако в интерфейсе Collection нет метода add().

Чтобы использовать переменную типа Collection как список, нам необходимо ключевое слово as. Оно сообщает модулю проверки типов, что мы намереваемся хранить в переменной типа Collection экземпляр List, то есть работать с коллекцией как со списком:

(permissionsCollection as List). atld(... какое-то полномочие ...):

Различия между интерфейсами Collection и List мы обсудим чуть ниже. А пока добавим в класс User из главы 7 новое поле, которое будет содержать коллекцию полномочий, как показано на рис. 8.3. Когда Алиса входит в систему, в эту коллекцию помещаются ее полномочия.

Добавляем коллекцию полномочий в класс User. Когда Алиса входит в систему, в эту коллекцию помещаются ее полномочия

Рис. 8.3. Добавляем коллекцию полномочий в класс User. Когда Алиса входит в систему, в эту коллекцию помещаются ее полномочия

Методы интерфейса Collection

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

В листинге 8.2 приведен код функции, которая возвращает список административных полномочий из коллекции, применяя к каждому ее элементу ключевое слово is, которое возвращает true, если этот элемент является объектом класса AdminPermission. Функция filter() из интерфейса Collection принимает в качестве параметра анонимную функцию, вызываемую для каждого элемента (полномочия).

Если эта функция возвращает true, то полномочие добавляется в возвращаемый результат.

Совет. Анонимная функция, которая вызывается для каждого элемента коллекции и возвращает true или false, называется предикатом.

Листинг 8.2. Возврат списка объектов класса AdminPermission

Возвращает коллекцию, которая

Collection extractAdminPermissions(User user) { *?является списком полномочий

return user.permissions.filter! (currentPermission) { _

return currentPermission is AdminPermission;

>); Предикат возвращает true, если currentPermission - экземпляр класса AdminPermission. } В ответ currentPermission добавляется в возвращаемый результат

Передав функции extractAdminPermissionsQ объект User, представляющий Алису, мы получаем новый объект Collection, который содержит все административные полномочия пользователя.

Еще один полезный метод интерфейса Collection - функция some(), которая позволяет узнать, содержится ли в коллекции элемент (полномочие), удовлетворяющий некоторому условию. Эта функция принимает предикат и возвращает true, если предикат вернул true хотя бы для одного элемента коллекции. Например, чтобы узнать, есть ли у Алисы полномочие ALLOW_CREATE, мы можем вызвать some(), как показано ниже, и запомнить результат в переменной containsAllowCreate:

Предикат, записанный в короткой форме, вызывается для каждого элемента коллекции. Функция some() возвращает true, если предикат вернул

bool containsAllowCreate = user, permissions. some( true хотя бы для одного элемента (currentPerm) => currentPerm == AdminPemission. ALLOW_CHEATE;

1-

Обход коллекции

Интерфейс Collection наследует интерфейсу Iterable, который позволяет использовать конструкцию for( in ). Синтаксис этой конструкции такой же, как в JavaScript, а семантически она аналогична предложениям foreach( in ) в C# и for( : ) в Java. Эта конструкция позволяет обойти коллекцию, поочередно присваивая каждый ее элемент переменной, как показано на рис. 8.4.

Конструкция for (... in ...) позволяет перебрать все элементы коллекции

Рис. 8.4. Конструкция for (... in ...) позволяет перебрать все элементы коллекции

Конструкция for ( in ) дает удобный способ обойти все элементы списка. Чтобы досрочно выйти из цикла, например после обнаружения первого подходящего полномочия, применяется ключевое слово

break: for (Permission permission in user.permissions) {

if (permission is AdminPermission) { *- Найден первый объект типа AdminPermission break; *- Сразу выходим из цикла

)

Обход коллекции вручную

Интерфейс Iterable возвращает интерфейс Iterator, который используется автоматически в конструкции for (...in...), но его свойство hasNext и метод next() можно вызывать и явно для обхода коллекции вручную. Свойство hasNext возвращает true, если имеется следующий элемент; метод next() возвращает следующий элемент и перемещает итератор на одну позицию вперед. Если итератор уже находился за последним элементом, то возбуждается исключение StateError. В примере ниже из коллекции извлекаются первые два элемента. Метод коллекции iterator() возвращает новый итератор, который позиционирован перед первым элементом.

Листинг 8.3. Извлечение первых двух элементов коллекции с помощью итератора

Iterator iterator = user, permissions, iterator!); *? Получаем новый итератор, var perml = null; I Создаем переменные позиционированный перед первым

var perm2 = null: | для хранения полномочий элементом if (iterator. hasNext) { *? Проверяем, есть ли следующий элемент

perml = iterator.next(); Возвращаем следующий элемент и сдвигаем итератор вперед

}

if (iterator. hasNext) { Проверяем наличие perm2 = iterator. next(); и возвращаем второй элеменг

}

 
Посмотреть оригинал
< Пред   СОДЕРЖАНИЕ ОРИГИНАЛ   След >