Язык программирования Перфолента.Net - Официальный сайт

 Язык программирования Перфолента.Net - Официальный сайт.

Поиск   
Главная :: О проекте :: Контакты :: Обратная связь :: Благодарности :: ВходГость

   >   >   >   > 



Перечисления в языке Перфолента.

Во многих случаях программисту необходимо использовать в программе наборы заранее заданных значений. Перечисления - это способ записи и использования таких наборов значений.


Придется использовать перечисление ТипыПричесок.

«Синий, красный, голубой, выбирай себе любой.»

Очень часто при написании программы возникает необходимость работы с небольшими списками именованных сущностей. Например, это может быть список дней недели, список месяцев, список цветов радуги, список состояний объекта и т.д.

В старые добрые времена, когда компьютеры были большими, а компиляторы маленькими, значения таких списков представляли числами, а какое число соответствует какому значению записывали на листочке бумаги. При чтении программы часто было трудно понять, что это за числа, поэтому программисты называли их «магические числа».

Однако, по мере увеличения оперативной памяти компьютеров, программисты смогли себе позволить записывать эти списки прямо в программе, сначала как комментарии, а затем и как наборы констант. Получилось примерно так:

Константа ПОНЕДЕЛЬНИК = 1

Константа ВТОРНИК = 2

… и т.д.

Константа ЯНВАРЬ = 1

Константа ФЕВРАЛЬ = 2

… и т.д.

Это уже даёт возможность писать в программе имена вместо чисел, например, так:

Если Месяц = ЯНВАРЬ Тогда
    // код блока
КонецЕсли

Отлично, но не лишено недостатков.

По мере того, как констант в вашей программе становится всё больше и больше, становится трудным делом запомнить все их имена. В случае дней недели или месяцев такой проблемы нет, но в случае списка состояний какого-либо объекта или списка специфических параметров эта проблема возникает.

Вторая проблема состоит в том, что среда разработки (IDE) не может Вам подсказать список дней недели, а компилятор не может проверить, не подсунули ли Вы ему вместо января четверг. Становятся необходимостью группировка констант по смыслу и типизация, т.е. включение их в систему типов языка.

Третья проблема состоит в том, что в разных библиотеках могут появиться константы с одинаковыми именами, но различными значениями. К тому же, в большинстве языков программирования константы являются внутренними сущностями, которые не видны программам, использующим библиотеку.

В результате, во многих языках программирования появился новый тип данных – перечисление, который за счет группировки имен констант по смыслу, типизации и возможной видимости извне, решил выше описанные проблемы.

Перечисление – это тип данных, представляющий именованный список именованных значений.

 

 

Синтаксис перечислений.

В языке программирования Перфолента.Net, перечисления играют важную роль. В стандартной библиотеке языка их очень много. К тому же программист имеет возможность создавать свои собственные перечисления, как для использования внутри текущей программы, так и для использования другими программами.

Полный синтаксис объявления перечисления выглядит так:

&ВидноВсем
Перечисление ИмяПеречисления тип ТипПеречисления
    ИмяЗначения1 = Значение1
    ИмяЗначения2 = Значение2
    // ...
    ИмяЗначенияН = ЗначениеН
КонецПеречисления

Тип перечисления не может быть любым, т.к. среда выполнения Net ограничивает допустимые типы перечислений списком целых числовых типов: Байт, Целое, Цел8, Цел16, Цел32, Цел64, Бит8, Бит16, Бит32, Бит64.

Если тип перечисления не указан, то по умолчанию используется тип Целое.

Значения задаются числовыми литералами.

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

Блок Перечисление может быть вложен в классы, модули, структуры и интерфейсы. Подробнее о структуре программы можно почитать в статье «Структура программы на языке Перфолента.Net»

Приведём пример перечисления:

Перечисление ТипыПринтеров
    Матричный = 0
    Лазерный = 1
    Струйный = 2
    Другой = 999
КонецПеречисления

Обратите внимание, что в этом примере использовано имя перечисления во множественном числе, а значения перечисления в единственном числе. Такой способ считается предпочтительным, но не обязательным.

Любители записать всё в одну строку должны не забывать про разделительные точки с запятой.

Перечисление ДаНет; @Да; @Нет; КонецПеречисления

Обратите внимание, что перед именами Да и Нет, являющимися ключевыми словами языка, стоит экранирующий символ @.

 

Поля в перечислениях.

Поля в перечислениях являются единственным возможным типом членов. Поэтому они создаются без ключевого слова Поле и по умолчанию имеют атрибут ВидноВсем. Указывать тип полей нельзя, т.к. все они имеют тип перечисления.

Отдельно остановимся на инициализации полей в перечислениях. Вы можете задать полю значение того типа, который указан как тип перечисления. Однако, Вы можете оставить инициализацию компилятору. В этом случае компилятор назначит значения полям, у которых значение не задано, с помощью счетчика, начиная со значения 0. При этом значения заданные вручную пропускаются.

Обратите внимание на то, что несколько полей перечисления могут иметь одинаковые значения. В том числе значение установленное вручную может совпасть со значением назначенным компилятором.

//в этом примере поля перечисления инициализированы вручную
Перечисление ПородыСобак тип Целое
    Овчарка = 1
    Бульдог = 2
    Такса = 3
    //два следующих поля имеют одинаковые значения
    Доберман = 4
    ПохожаНаДобермана = 4
    //...
КонецПеречисления

//в этом примере поля будут инициализированы компилятором
Перечисление ПородыСобак тип Целое
    Овчарка //поле получит значение 0
    Бульдог //поле получит значение 1
    Такса //поле получит значение 2
    Доберман //поле получит значение 3
    //...
КонецПеречисления

//в этом примере часть полей инициализированы вручную,
//а часть полей будут инициализированы компилятором
Перечисление ПородыСобак тип Целое
    Овчарка //поле получит значение 0
    Бульдог = 99 //полю вручную задано значение 99
    Такса //поле получит значение 1
    Доберман //поле получит значение 2
    //значение следующего поля установленное вручную совпадает
    //с назначенным компилятором для предыдущего поля
    ПохожаНаДобермана = 2 //полю вручную задано значение 2
    //...
КонецПеречисления

 

Использование перечислений.

Так как Перечисление — это полноценный тип данных, имя перечисления может использоваться везде, где можно указать тип. Однако, только значение перечисления можно присвоить переменной, полю, свойству или передать как параметр в метод.

Приведем примеры правильного и не правильного использования перечислений:

ТП = ТипыПринтеров //Ошибка, имя перечисления не может использоваться как значение
МП = ТипыПринтеров.Лазерный //Правильно
ПроверитьПринтер(ТипыПринтеров) //Ошибка
ПроверитьПринтер(Струйный) //Ошибка
ПроверитьПринтер(ТипыПринтеров.Струйный) //Правильно

Процедура ПроверитьПринтер(ТипПринтера тип ТипыПринтеров)
       
       ВыводСтроки "Тип принтера: "+ТипПринтера
       ВыводСтроки "Тип значения: "+ТипЗнчСтр(ТипПринтера)
       
       Выбор Для ТипПринтера
       Когда ТипыПринтеров.Матричный Тогда
           //печатаем на матричном принтере
       Когда ТипыПринтеров.Лазерный Тогда
           //печатаем на лазерный принтере
       Когда ТипыПринтеров.Струйный Тогда
           //печатаем на струйном принтере
       Иначе
           //ошибка, не знаем как печатать на другом принтере 
       КонецВыбора
КонецПроцедуры

 

 

Перечисления как наборы флагов.

Лирическое отступление: Что за флаги имеются ввиду? В те времена, когда средствами связи выступали гонцы на лошадях и почтовые голуби, были придуманы простые средства зрительной коммуникации – сигнальные костры и флаги. Так же, как дым костра виден далеко, так и флаг поднятый на высоком флагштоке хорошо заметен на большом расстоянии. Поднятый флаг говорит о том, о чем заранее договорились сигнализатор и наблюдатель. До высокой степени совершенства общение с помощью флагов довели моряки, которые используют этот способ коммуникации даже сегодня. Затем эстафету подхватили железнодорожники, которые создали семафоры по принципу поднятия флага. А когда появились компьютеры, термины флаги и семафоры перекочевали и туда. В двоичной системе каждый разряд числа может содержать либо ноль, либо единицу. Ноль означает, что флаг опущен, а единица, что флаг поднят. Таким образом восьмиразрядное двоичное число содержит восемь флагов, каждый из которых можно поднять или опустить с помощью поразрядных логических операций.

Обычное перечисление позволяет выбрать одно из имеющихся значений и использовать его при вызове метода или присвоении переменной, свойству или полю.

Однако, в некоторых случаях было бы удобно выбирать сразу несколько значений.

Конечно, для этой цели можно создать структуру или класс с набором полей типа Булево, но если значений будет менее 64-х, то вместо структуры или класса можно использовать перечисление, устанавливая отдельные биты в целом числе, которым и является перечисление.

Например, вместо структуры:

Структура ВозможностиГероя 
    &ВидноВсем Поле Быстрый  тип Булево
    &ВидноВсем Поле Меткий  тип Булево
    &ВидноВсем Поле Сильный  тип Булево
    &ВидноВсем Поле Смелый  тип Булево
    &ВидноВсем Поле Сообразительный  тип Булево
КонецСтруктуры

Можно создать перечисление:

&Флаги
Перечисление ВозможностиГероя
    //простые флаги
    Обычный = 0
    Быстрый = 1
    Меткий = 2
    Сильный = 4
    Смелый = 8
    Сообразительный = 16
    //комплексные флаги
    БыстрыйИСильный = 5 //1+4
    СильныйИСмелый = 12 //4+8
    СамыйКрутой = 31 //1+2+4+8+16
КонецПеречисления

Такое перечисление занимает в памяти компьютера всего 4 байта и позволяет иметь 32 битовых флага. Количество доступных флагов зависит от разрядности числа использованного в качестве типа перечисления. Если типом перечисления является Байт, то у Вас есть 8 флагов, а если использовать типы Цел64 или Бит64, то можно использовать 64 флага.

Атрибут Флаги не является обязательным, он просто говорит программисту, читающему код, что перечисление является набором битовых флагов. К тому же, этим атрибутом может воспользоваться среда разработки, чтобы сформировать актуальную подсказку при наборе кода.

Значения перечисления, являющегося набором флагов, делятся на два вида:

·         простые флаги – значения равные степеням двойки, у которых в двоичном виде присутствует только одна единица, например, 00010;

·         комплексные флаги – значения, являющиеся суммой нескольких простых флагов, у которых в двоичном виде присутствует несколько единиц, например, 10110;

Комплексные флаги можно задать заранее, как показано в приведенном выше примере, или их можно создавать во время выполнения программы с помощью оператора БитИли.

БыстрыйИМеткий = ВозможностиГероя.Быстрый БитИли ВозможностиГероя.Меткий

Как это работает? Значению Быстрый соответствует двоичное число 00001, а значению Меткий 00010. После операции БитИли получится двоичное число 00011, которое содержит единицы в тех же разрядах числа, где были единицы у значений Быстрый и Меткий.

Добавим еще одну возможность нашему герою, т.е. установим еще один флаг:

СмелыйБыстрыйИМеткий = БыстрыйИМеткий БитИли ВозможностиГероя.Смелый

Теперь нам осталось научится проверять установлен ли интересующий нас флаг и можно считать, что работа с наборами флагов у нас в кармане.

Для проверки одного или нескольких флагов можно использовать поразрядную логическую операцию БитИ, сравнивая проверяемое число с проверочным числом, у которого установлены нужные флаги.

// проверим, что герой смелый
Если БыстрыйИМеткий БитИ ВозможностиГероя.Смелый = ВозможностиГероя.Смелый
        ВыводСтроки "Герой смелый"
Иначе
        ВыводСтроки "Герой НЕ смелый"
КонецЕсли
//проверим, что герой быстрый
Если БыстрыйИМеткий БитИ ВозможностиГероя.Быстрый = ВозможностиГероя.Быстрый
        ВыводСтроки "Герой быстрый"
Иначе
        ВыводСтроки "Герой НЕ быстрый"
КонецЕсли

Всё, теперь работа с перечислением, как с набором флагов, не станет для Вас проблемой.

 

 

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




К началу статьи


Предыдущая статья:
Директивы препроцессора. Выполнение действий перед компиляцией.

Следующая статья:
Инициализаторы объектов

Вернуться в раздел:
Синтаксис языка Перфолента
  Поддержи проект!

Вы можете поддержать разработку Перфоленты, перечислив любую удобную сумму, которая пойдет на развитие языка и поддержку инфраструктуры сайта.

  Новости:
      04.01.2025 Опубликован новый релиз дистрибутива языка программирования Перфолента.Net версии 0.4.15.0_CE
      23.09.2024 Опубликована новая статья: "Конструируем класс. Делегаты."
      30.08.2024 Опубликован новый релиз дистрибутива языка программирования Перфолента.Net версии 0.4.14.0
      24.05.2024 Обновлён справочный раздел сайта
      01.07.2023 Новая версия 0.4.13.0 языка программирования Перфолента.Net
       Все новости