Перечисления в ABAP

До версии языка 7.51 чтобы предоставить фиксированный набор значений, например, для передачи в методы нашего API, приходилось использовать именованные константы и вручную реализовывать контроль ввода значений этих констант. Типичный пример стандартного API по работе с SALV:

Значением по умолчанию мы могли дать представление разработчикам использующим наше API, откуда они могут взять значения констант. Однако никакого контроля со стороны языка на этапе активации система не производит, что позволяет передавать в целом любые значения из диапазона типа I. Контроль на этапе выполнения уже оставался на совести разработчика API.

Начиная с версии языка 7.51 у нас появилась возможность объявлять так называемые перечисляемые типы. Причём контроль за вводом осуществляется уже на уровне языка. Далее разберём как именно их можно использовать.

Но для начала простой вариант эмуляции перечисляемого типа до версии 7.51:

При создании объекта класса shirt мы обязаны указать его размер, который обязательно должен быть одним из значений объявленных в именованной группе констант gc_sizes, в противном случае мы вызовем исключение, которое необходимо обработать в клиентском коде:

В данном примере есть два существенных недостатка:

  • Необходим контроль на уровне API за передаваемыми значениями,
  • Необходима дополнительная обработка исключений в клиентском коде.

Рассмотрим еще один пример, но уже на базе ООП:

Данный пример лишён предыдущих недостатков, т.к. создавать инстанции класса может только он сам (CREATE PRIVATE), в клиентском коде не требуется доп. контроля. Однако так или иначе требуется дополнительное кодирование, которое в случае встроенных перечисляемых типов можно избежать.

Давайте перепишем наш пример с использованием определения перечисляемого типа:

Как видно кода стало заметно меньше. Перечисляемый тип создаётся с помощью ключевых слов BEGIN OF ENUM.. END OF ENUM. Используемый по умолчанию тип данных для компонентов перечисляемого типа — I (целое), причем значения начинаются с 0. Т.е. конструкцию из примера можно было бы заменить на такую (с явным указанием базового типа):

При явном указании типа в каждом перечислении должно быть явно объявлено INITIAL значение. Сделана такая проверка для возможности использования конструкции IS INITIAL к переменным перечисляемого типа. Указание базового типа позволяет выполнить рефакторинг существующих до 7.51 перечислений к новому синтаксису, однако следует учитывать ряд ограничений:

  • Можно использовать все числовые типы, типы даты и времени,
  • Символьные типы не могут иметь значения более 8 символов,
  • Байтовые не более 16,
  • Нельзя использовать string и xstring.

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

Однако если в рамках текущей области видимости объявляются два типа перечислений с одинаковыми именами, возникнет ошибка:

Чтобы такого не происходило, используется дополнение STRUCTURE:

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

Несмотря на то, что компоненты перечисляемого типа имеют заданный базовый тип, напрямую передавать значения такого типа (вместо компонентов) уже нельзя:

Однако можно воспользоваться явной конвертацией к типу:

Если конвертация не может быть выполнена, возникнет исключение CX_SY_CONVERSION_NO_ENUM_VALUE.

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

Но явная конвертация к типу может нам помочь:

Результат: 30, т.к. базовый тип перечисляемого типа в данном случае это i, начинается с 0, значение для XL = 3.

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

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

Система описания типов RTTI так же была расширена на специальный класс для работы с перечисляемыми типами:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *