Перечисления в языке Перфолента
Содержание
Отличие Словарей в Питоне от Перечислений в Перволенте.Net, C#
Словари в Python - неупорядоченные коллекции произвольных объектов с доступом по ключу. Их иногда ещё называют ассоциативными массивами или хеш-таблицами.
Словарь в питоне, это коллекция в которую значения добавляются во время выполнения программы. А перечисления создаются во время компиляции и не могут изменяться во время выполнения, т.е. перечисление это именованный список именованных констант.
Начало
Во многих случаях программисту необходимо использовать в программе наборы заранее заданных значений. Перечисления - это способ записи и использования таких наборов значений.
Очень часто при написании программы возникает необходимость работы с небольшими списками именованных сущностей. Например, это может быть список дней недели, список месяцев, список цветов радуги, список состояний объекта и т.д.
В старые добрые времена, когда компьютеры были большими, а компиляторы маленькими, значения таких списков представляли числами, а какое число соответствует какому значению записывали на листочке бумаги. При чтении программы часто было трудно понять, что это за числа, поэтому программисты называли их «магические числа».
Однако, по мере увеличения оперативной памяти компьютеров, программисты смогли себе позволить записывать эти списки прямо в программе, сначала как комментарии, а затем и как наборы констант. Получилось примерно так:
Константа ПОНЕДЕЛЬНИК = 1 Константа ВТОРНИК = 2
… и т.д.
Константа ЯНВАРЬ = 1 Константа ФЕВРАЛЬ = 2
… и т.д.
Это уже даёт возможность писать в программе имена вместо чисел, например, так:
Если Месяц = ЯНВАРЬ Тогда // код блока КонецЕсли
Отлично, но не лишено недостатков.
Первая проблема: по мере того, как констант в вашей программе становится всё больше и больше, становится трудным делом запомнить все их имена. В случае дней недели или месяцев такой проблемы нет, но в случае списка состояний какого-либо объекта или списка специфических параметров эта проблема возникает.
Вторая проблема состоит в том, что среда разработки (IDE) не может Вам подсказать список дней недели, а компилятор не может проверить, не подсунули ли Вы ему вместо января четверг. Становятся необходимостью группировка констант по смыслу и типизация, т.е. включение их в систему типов языка.
Третья проблема состоит в том, что в разных библиотеках могут появиться константы с одинаковыми именами, но различными значениями. К тому же, в большинстве языков программирования константы являются внутренними сущностями, которые не видны программам, использующим библиотеку.
В результате, во многих языках программирования появился новый тип данных – перечисление, который за счет группировки имен констант по смыслу, типизации и возможной видимости извне, решил выше описанные проблемы.
Перечисление – это тип данных, представляющий именованный список именованных значений.
Синтаксис перечислений
В языке программирования Перфолента.Net, перечисления играют важную роль. В стандартной библиотеке языка их очень много. К тому же программист имеет возможность создавать свои собственные перечисления, как для использования внутри текущей программы, так и для использования другими программами.
Полный синтаксис объявления перечисления выглядит так:
&ВидноВсем Перечисление ИмяПеречисления тип ТипПеречисления ИмяЗначения1 = Значение1 ИмяЗначения2 = Значение2 // ... ИмяЗначенияН = ЗначениеН КонецПеречисления
Тип перечисления не может быть любым, т.к. среда выполнения Net ограничивает допустимые типы перечислений списком целых числовых типов: Байт, Целое, Цел8, Цел16, Цел32, Цел64, Бит8, Бит16, Бит32, Бит64.
Если тип перечисления не указан, то по умолчанию используется тип Целое.
Значения задаются числовыми литералами.
Приведём пример перечисления:
Перечисление ТипыПринтеров Матричный = 0 Лазерный = 1 Струйный = 2 Другой = 999 КонецПеречисления
Обратите внимание, что в этом примере использовано имя перечисления во множественном числе, а значения перечисления в единственном числе. Такой способ считается предпочтительным, но не обязательным.
Если значение элемента перечисления не указано, то ему автоматически присваивается значение из последовательности, начинающейся с нуля.
Перечисление ТипыПринтеров Матричный // Будет присвоено 0 Лазерный // Будет присвоено 1 Струйный // Будет присвоено 2 Другой // Будет присвоено 3 КонецПеречисления
Блок Перечисление может быть вложен в классы, модули, структуры и интерфейсы. Подробнее о структуре программы можно почитать в статье «Структура программы на языке Перфолента.Net»
Любители записать всё, в компактной форме, в одну строку должны не забывать про разделительные точки с запятой.
Перечисление ДаНет; @Да; @Нет; КонецПеречисления
Обратите внимание, что перед именами Да и Нет, являющимися ключевыми словами языка Перфолента.Net, стоит экранирующий символ @.
Использование перечислений
Так как Перечисление — это полноценный тип данных, имя перечисления может использоваться везде, где можно указать тип. Однако, только значение перечисления можно присвоить переменной, полю, свойству или передать как параметр в метод.
Приведем примеры правильного и не правильного использования перечислений:
ТП = ТипыПринтеров //Ошибка, имя перечисления не может использоваться как значение МП = ТипыПринтеров.Лазерный //Правильно ПроверитьПринтер(ТипыПринтеров) //Ошибка ПроверитьПринтер(Струйный) //Ошибка ПроверитьПринтер(ТипыПринтеров.Струйный) //Правильно
Процедура ПроверитьПринтер(ТипПринтера тип ТипыПринтеров) ВыводСтроки "Тип принтера: "+ТипПринтера ВыводСтроки "Тип значения: "+ТипЗнчСтр(ТипПринтера) Выбор Для ТипПринтера Когда ТипыПринтеров.Матричный Тогда //печатаем на матричном принтере Когда ТипыПринтеров.Лазерный Тогда //печатаем на лазерный принтере Когда ТипыПринтеров.Струйный Тогда //печатаем на струйном принтере Иначе //ошибка, не знаем как печатать на другом принтере КонецВыбора КонецПроцедуры
Вывод: Перечисления - это вид констант. Перчисления удобны в тех случаях, когда в программе необходимо использовать именованные значения из небольшого, заранее известного списка.
Перечисления как наборы флагов
Лирическое отступление: Что за флаги имеются ввиду? В те времена, когда средствами связи выступали гонцы на лошадях и почтовые голуби, были придуманы простые средства зрительной коммуникации – сигнальные костры и флаги. Так же, как дым костра виден далеко, так и флаг поднятый на высоком флагштоке хорошо заметен на большом расстоянии. Поднятый флаг говорит о том, о чем заранее договорились сигнализатор и наблюдатель. До высокой степени совершенства общение с помощью флагов довели моряки, которые используют этот способ коммуникации даже сегодня. Затем эстафету подхватили железнодорожники, которые создали семафоры по принципу поднятия флага. А когда появились компьютеры, термины флаги и семафоры перекочевали и туда. В двоичной системе каждый разряд числа может содержать либо ноль, либо единицу. Ноль означает, что флаг опущен, а единица, что флаг поднят. Таким образом восьмиразрядное двоичное число содержит восемь флагов, каждый из которых можно поднять или опустить с помощью поразрядных логических операций.
Обычное перечисление позволяет выбрать одно из имеющихся значений и использовать его при вызове метода или присвоении переменной, свойству или полю.
Однако, в некоторых случаях было бы удобно выбирать сразу несколько значений.
Конечно, для этой цели можно создать структуру или класс с набором полей типа Булево (логическая переменная да/нет, правда/ложь), но если значений будет менее 64-х, то вместо структуры или класса можно использовать перечисление, устанавливая отдельные биты в целом числе, которым и является перечисление.
Например, вместо структуры:
Структура ВозможностиГероя &ВидноВсем Поле Быстрый тип Булево &ВидноВсем Поле Меткий тип Булево &ВидноВсем Поле Сильный тип Булево &ВидноВсем Поле Смелый тип Булево &ВидноВсем Поле Сообразительный тип Булево КонецСтруктуры
Можно создать перечисление:
&Флаги Перечисление ВозможностиГероя //простые флаги Обычный = 0 Быстрый = 1 Меткий = 2 Сильный = 4 Смелый = 8 Сообразительный = 16 //комплексные флаги - являются суммой простых флагов БыстрыйИСильный = 5 //1+4 СильныйИСмелый = 12 //4+8 СамыйКрутой = 31 //1+2+4+8+16 КонецПеречисления
Можно легко проверить что любое число (в данном примере более 16) можно получить только единственной комбинацией сумм предыдущих чисел, при этом каждое следующее число д.б. в два раза больше предыдущего. Т.о. из любого числа больше 16 можно определить суммой каких простых флагов он является.
Такое перечисление занимает в памяти компьютера всего 4 байта и позволяет иметь 32 битовых флага. Количество доступных флагов зависит от разрядности числа использованного в качестве типа перечисления. Если типом перечисления является Байт, то у Вас есть 8 флагов, а если использовать типы Цел64 или Бит64, то можно использовать 64 флага.
Атрибут &Флаги не является обязательным, он просто говорит программисту, читающему код, что перечисление является набором битовых флагов. К тому же, этим атрибутом может воспользоваться среда разработки, чтобы сформировать актуальную подсказку при наборе кода.
Значения перечисления, являющегося набором флагов, делятся на 2 вида:
- простые флаги – значения равные степеням двойки, у которых в двоичном виде присутствует только одна единица, например, 00010;
- комплексные флаги – значения, являющиеся суммой нескольких простых флагов, у которых в двоичном виде присутствует несколько единиц, например, 10110;
Комплексные флаги и БитИли
Комплексные флаги можно задать заранее, как показано в приведенном выше примере, или их можно создавать во время выполнения программы с помощью оператора БитИли.
БыстрыйИМеткий = ВозможностиГероя.Быстрый БитИли ВозможностиГероя.Меткий
Как это работает? Значению Быстрый соответствует двоичное число 00001, а значению Меткий 00010. После операции БитИли получится двоичное число 00011, которое содержит единицы в тех же разрядах числа, где были единицы у значений Быстрый и Меткий.
Добавим еще одну возможность нашему герою, т.е. установим еще один флаг:
СмелыйБыстрыйИМеткий = БыстрыйИМеткий БитИли ВозможностиГероя.Смелый
БитИ проверка установки интересующего флага
Теперь нам осталось научится проверять установлен ли интересующий нас флаг.
Для проверки одного или нескольких флагов можно использовать поразрядную логическую операцию БитИ, сравнивая проверяемое число с проверочным числом, у которого установлены нужные флаги.
// проверим, что герой смелый Если БыстрыйИМеткий БитИ ВозможностиГероя.Смелый = ВозможностиГероя.Смелый ВыводСтроки "Герой смелый" Иначе ВыводСтроки "Герой НЕ смелый" КонецЕсли //проверим, что герой быстрый Если БыстрыйИМеткий БитИ ВозможностиГероя.Быстрый = ВозможностиГероя.Быстрый ВыводСтроки "Герой быстрый" Иначе ВыводСтроки "Герой НЕ быстрый" КонецЕсли
Всё, теперь работа с перечислением, как с набором флагов, не станет для Вас проблемой.
Вывод: Перечисления удобны в тех случаях, когда в программе необходимо использовать именованные значения из небольшого, заранее известного списка. Перечисления обеспечивают группировку значений по смыслу, типизацию и возможность использовать их, как наборы флагов.
Cм. также
Синтаксис языка Перфолента
2.1 Переменные. Объявление переменных, инициализация и их использование
2.2 Типы данных в языке Перфолента
2.3 Массивы. Создание массивов, заполнение данными, обращения к элементам и другие операции с массивами
2.4 Структура программы на языке Перфолента.Net
2.7 Оператор условного выбора блока кода Выбор Для
2.8 Функции и процедуры в языке Перфолента
2.9 Оператор Попытка. Структурная обработка ошибок
2.10 Работа с файлами
2.11 Директивы препроцессора. Выполнение действий перед компиляцией
Практика программирования на языке Перфолента
3.1. Многозадачность и многопоточность в языке Перфолента.Net
Ссылки
- ПРОМКОД - Перечисления в языке Перфолента. Первоисточник.