Как ответить на число вопрос?

С появлением возможности выполнять множество операций через компьютер или мобильное устройство, имеющее доступ к сети интернет, в частности — связанных с денежными переводами, важнейшим вопросом стало обеспечение безопасности таких действий. Помимо стандартной процедуры подтверждения действия через звонок или смс, отправленное на определенный номер телефона, была разработана бесплатная программа E-num, особенности которой будут рассмотрены в этой статье.

Содержание

E-num — что это такое?

E-num – сервис, который создан для подтверждения определенных действий пользователями интернет-сети. Механизм его работы в следующем: сервис генерирует пару случайных чисел, одно из которых называется «вопрос», а соответствующее ему – «ответ». Ответ приходит на мобильное устройство пользователя – мобильный телефон или планшет, на котором установлена данная программа.

Также E-num позволяет сканировать QR-код – грифическое изображение, в котором зашифрован ответ, предоставляющий доступ к нужному сервису или подтверждающий операцию.

QR-код дает возможность использовать систему E-num даже при отсутствии интернета на мобильном устройстве.

Среди аналогов сервиса – отправка клиенту смс-сообщения с ключом-ответом, за которую в некоторых случаях взимается дополнительная плата. Поэтому E-num более экономически выгоден – само приложение бесплатное и доступно для скачивания на мобильные устройства с любой операционной системой. Среди программ сервис не имеет аналогов и покрывает почти все совершаемые в сети финансовые операции.

Как используется Enum в WebMoney

Сфера применения этого способа авторизации – различные интернет-магазины, порталы и электронные банковские системы. Часто пользователи впервые сталкиваются с ним при регистрации электронного кошелька WebMoney. В этом случае мобильный клиент потребуется при входе на сайт или в кипер, для доступа к некоторым разделам, содержащим личную информацию (например, ранее загруженные сканы паспортов), а также для подтверждения операций перевода средств между кошельками или их вывода и обналичивания.

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

На данный момент количество скачиваний программы из ПлэйМаркета превысило 500 тысяч, средняя оценка приложения – стабильная четверка и выше. Пользователей остальных ОС в сумме набирается также около 300 тысяч. Много это или мало? При общем количестве клиентов систем Вебмани Трансфер в 10 миллионов человек становится понятно, что распространенность системы Е-нам на данный момент низкая, но ее популярность действительно постепенно растет с увеличением доверия населения к электронным системам.

Интересно:  Что такое Blockchain: технология будущего?

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

Чтобы начать использовать E-num на мобильном устройстве с ОС Андроид необходимо скачать установочный файл с расширением *.apk с официального сайта или установить приложение из Play Маркета. Сама программа интуитивно понятная и ее использование не вызывает затруднений. Сразу после установки система предложит войти в свой аккаунт, а при отсутствии оного – зарегистрировать его.

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

Современные смартфоны и планшеты предоставляют пользователям возможность установки графического или цифрового пароля на приложение. В случае с E-num данная функция встроена в саму программу, но рекомендуется не пренебрегать дополнительными мерами безопасности и установить блокировку на само приложение. В случае кражи мобильного устройства это усложнит задачу злоумышленникам.

Помимо операционной системы Андроид, клиент E-num также разработан для пользователей следующих операционных систем:

  • Apple iOS;
  • WindowsPhone;
  • BlackBerry.

На официальном сайте E-num, а также на странице Wiki.WebMoney, посвященной данному клиенту, есть ссылки на установку приложения.

Важно! Не рекомендуется скачивать установочные файлы с других сайтов. Велик риск вместе с файлом получить вирус. Если при установке приложения возникают проблемы – необходимо обратиться в службу поддержки приложения.

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

Пошаговая инструкция по установке на телефон

  1. На официальном сайте приложения или через Play Маркет (Appstore и др. приложения в зависимости от ОС) загружается установочный файл.
  2. После достижения шкалой загрузки файла 100% необходимо нажать на окно «Установка файла», согласиться с условиями приложения – среди них «Получение данных через Интернет» и «Получение текстовых сообщений» или дождаться его автоматической установки.
  3. На экране появится окно «Открыть приложение». На стартовой странице будет предложено ввести электронную почту, на которую зарегистрирован ваш E-num аккаунт или зарегистрировать новый.
  4. После подтверждения аккаунта через электронную почту можно начинать работу с приложением – сканировать QR-коды, принимать на мобильный числа-ответы или генерировать собственные.

Интересно:  Bitcoin: что это такое?

Нюансы установки E-num

  • Объем памяти, которую занимает приложение — около 30 Мб, поэтому при установке на современные смартфоны с большим запасом памяти проблем не возникает.
  • В настройках при установке приложения можно выбрать методы его защиты: при помощи числового пароля или графического ключа, а также внешний вид окна, активность Push-уведомлений.

Внимание! Пункт настроек «Деактивация» сбрасывает емэйл и дает возможность зайти на другой аккаунт.

Безопасно ли использовать e-num?

Использование клиента безопасно по причине высокой надежности системы, которая обеспечивается как на архитектурном, так и на криптографическом уровне. Секретные ключи-ответы, которые появляются на экране мобильного телефона в момент совершения финансовых операций, дают возможность не привязываться к конкретному компьютеру и работать с электронными кошельками, переводить средства и совершать покупки в любой точке планеты. Возможность сканирования QR-кода гарантирует, что операция будет подтверждена, даже если есть проблемы с мобильным интернетом – достаточно навести камеру мобильного устройства на экран компьютера и установить ограничивающий красный луч в нужном месте.

Как подтвердить операцию с E-num

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

Вопрос-ответ

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

Плюсы:

  • простота и скорость подтверждения операции;
  • подходит для владельцев телефонов, с которых невозможно провести сканирование QR-кода (старые модели, дефекты объектива камеры).

Недостатки:

  • число-ответ находится на экране смартфона до 10 секунд, что доставляет некоторые неудобства – вводить приходится очень быстро.

Подтверждение операций через числовой «вопрос-ответ»- наиболее простой и экономически выгодный способ.

Подтверждение отпечатком

Подтверждение авторизации при помощи отпечатка – мало распространенный вариант, поскольку требует приобретения дополнительного оборудования – сканера отпечатков, например, фирмы Eikon. Данные устройства имеют вид флеш-накопителя, который подключается к компьютеру через USB-порт.

Интересно:  Регистрация кошелька Яндекс.Деньги

Для активации данного метода подтверждения операций необходимо зарегистрировать свой отпечаток пальца на сайте E-num. Можно ожидать, что в будущем станет доступна авторизация при помощи мобильных устройств последних поколений, в которые уже встроена функция распознавания отпечатков пальцев хозяина.

Плюсы:

  • скорость подтверждения и простота – достаточно приложить палец, и через несколько секунд доступ уже предоставлен;
  • максимальный уровень защиты от взлома.

Недостатки:

  • необходимость приобретения дополнительного устройства;
  • малая распространенность, как результат – работа команды E-num над данным методом на данный момент не ведется.

Подтверждение по СМС

Наиболее простой способ аутентификации – на мобильный номер клиента приходит сообщение с комбинацией цифр, которую необходимо ввести в специальном поле сайта.

Плюсы:

  • работает даже на устаревших моделях мобильных телефонов.

Недостатки:

  • зависимость от наличия мобильной сети;
  • в случае кражи мобильного телефона вместе с сим-картой упрощает хакерам взлом аккаунтов.

Где еще используется E-NUM

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

С развитием информационных технологий и перехода части рынка и банковского сегмента во Всемирную паутину главным становится вопрос безопасности совершаемых операций. Привычные методы подтверждения устаревают и часто являются экономически невыгодными для пользователя (за смс-сообщения с кодом подтверждения часто взимается дополнительная комиссия). При переходе на приложение E-num можно быть уверенным в его надежности, которая является главным фактором его популяризации.

.NET *C# * Recovery mode Из песочницы

За свою непродолжительную карьеру C# разработчика я успел поверхностно погрузиться во многие аспекты этого, без преувеличения, прекрасного языка. Наиболее любопытной из них для меня является такая, с первого взгляда, простая вещь, как перечисления или же enum, о коей я попытаюсь рассказать в этой статье.

Что же такое enum и на кой он вообще нужен?

Представим что нам необходимо определить такое свойство класса как цвет. Как же нам решить эту проблему?

Мы можем сделать это через строковую переменную:

public class ClassWithString {     public ClassWithString(string color)     {         Color = color;     }      public string Color { get; }      public bool IsDefinedColor(string otherColor)         => Color.Equals(otherColor); }
var redClass = new ClassWithString("Red");  var check = redClass.IsDefinedColor("Red");         //true var secondCheck = redClass.IsDefinedColor("Blue");  //false

В результате выполнения кода значение check будет равно true, а secondCheck будет равно false. Вроде бы задача решена, в прод. Но человек существо не идеальное, и может случиться такое, что в метод будет передано не Red, а red или rad. Вроде-бы человек может догадаться что было ему сказано, но машина прямолинейна и догадываться не будет. В результате некорректного ввода метод будет возвращать false, хотя мы ожидаем true:

var redClass = new ClassWithString("Red");  var check = redClass.IsDefinedColor("Red");         //true var secondCheck = redClass.IsDefinedColor("blue");  //false  var thirdCheck = redClass.IsDefinedColor("red");    //false var fourthCheck = redClass.IsDefinedColor("rad");   //false

Конечно первый вид опечатки можно исправить добавлением в Equals дополнительного параметра StringComparison.OrdinalIgnoreCase. Но этого не сделать при второй опечатке. Значит строки нам не особо подходят.

Color.Equals(otherColor, StringComparison.OrdinalIgnoreCase);

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

//0 - red //1 - blue public class ClassWithInt {     public ClassWithInt(int color)     {         Color = color;     }      public int Color { get; }      public bool IsDefinedColor(int otherColor)         => Color.Equals(otherColor); }

Вроде-бы проблема решена: теперь никто не опечатается при вводе кода цвета. Но здесь всплывает другая проблема: человек не машина, и работать со словами ему на порядок проще чем с числами. Постоянно помнить, что 0 – это красный, а 1 – это синий, никакой памяти не напасёшься. А если человек поменяет проект и под номером 0 будет белый, а под 1 черный? Ерунда какая-то!!!

И тут нам на помощь приходит генная инженерия, позволяющая нарушить базовые законы колдовства и естества. Мы можем скрестить числа и строки!!! После столь противоестественного действия мы и получим любимый мною enum.

Enum-ом в базовом понимании называют некий список возможных, заранее определенных, именованных значений. Нужен этот список для того, чтобы упростить работу разработчику в оперировании некими состояниями. Решим нашу задачу с применением enum.

public class ClassWithEnum {     public ClassWithEnum(Colors color)     {         Color = color;     }      public Colors Color { get; }      public bool IsDefinedColor(Colors otherColor)         => Color.Equals(otherColor);      public enum Colors     {         Red,         Blue     } }

Как можно увидеть внизу нашего класса мы определили тот самый enum и сказали, что он может принимать 2 значения: Red и Blue. Теперь повторим вызов из примера со строками:

var redClass = new ClassWithEnum(ClassWithEnum.Colors.Red);  var check = redClass.IsDefinedColor(ClassWithEnum.Colors.Red);         //true var secondCheck = redClass.IsDefinedColor(ClassWithEnum.Colors.Blue);  //false

Как можно заметить, всё понятно, ясно, чЁтКо. А теперь попытаемся опечататься:

var redClass = new ClassWithEnum(ClassWithEnum.Colors.Red);  var check = redClass.IsDefinedColor(ClassWithEnum.Colors.Red);         //true var secondCheck = redClass.IsDefinedColor(ClassWithEnum.Colors.Blue);  //false  var thirdCheck = redClass.IsDefinedColor(ClassWithEnum.Colors.red);    //Ошибка ввода var fourthCheck = redClass.IsDefinedColor(ClassWithEnum.Colors.rad);   //Ошибка ввода

Редактор кода говорит, что я дурачок и не умею правильно писать слова. А это значит, что я могу заметить ошибку ещё до сборки и гарантированно её замечу во время сборки. Спасибо, добрый блокнот.

В принципе на этом можно было бы и закончить статью, но тогда какой в ней смысл, если это повествование можно было сократить раза в четыре. Непорядок! Поэтому, после базового пояснения что такое enum и нафига он нужен будут настоящие сенсации. Внимание, барабанная дробь…

Enum это число!1!1!1

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

По сути enum это обыкновенное число с табличкой. В примере выше это было не явно потому, что в списке были только имена, но не было чисел. Это не совсем правильный, хотя и рабочий по причине автопроставления чисел, подход к определению enum-а. Более правильным будет следующий подход:

public enum Colors {     Red = 0,     Blue = 1 }

Из того, что enum – это число с бейджиком, следует несколько особенностей:

  • Возможность хранения нескольких булевых свойств в битовых флагах

  • Возможность приведения числа к enum.

  • Особенное приведение одного enum-а к другому.

Разберем эти особенности:

Битовые флаги

Предположим мы имеем некий объект, обладающий рядом булевых свойств. Мы, несомненно, можем описать их в виде нескольких самостоятельных полей типа bool. Данный подход является вполне приемлемым:

public class ClassWithBools {     public ConditionsBools Conditions { get; set; }          public class ConditionsBools     {         public bool HasSomething { get; set; }         public bool DoSomething { get; set; }         public bool HasAnother { get; set; }         public bool DoAnother { get; set; }     } }

Однако, есть иной способ определить эти атрибуты. Для этого мы можем использовать такую надстройку над enum-ом, как битовые флаги. Подобная конструкция представляет из себя обыкновенное enum-ом, обладающее атрибутом [Flags] и числовыми значениями, представляющими из себя степени двойки:

public class ClassWithFlags {     public ConditionsFlags Conditions { get; set; }          [Flags]     public enum ConditionsFlags     {         HasSomething = 1 << 0,  //0001 = 1         DoSomething = 1 << 1,   //0010 = 2         HasAnother = 1 << 2,    //0100 = 4         DoAnother = 1 << 3      //1000 = 8     } }</code>

Как же работать с бинарным флагом? В случае использования отдельных булевых переменных всё достаточно очевидно: обращайся к конкретной переменной и читай или же присваивай значение. Но в случае же работы битовыми флагами приходится использовать базовые двоичные операции: конъюнкция (И, &) и дизъюнкция (ИЛИ, |).

Операция ИЛИ позволяет вернуть множество, содержащее в себе все подмножества, используемые в данной операции:

Демонстрация дизъюнкции множеств П и У на картинках из интернетов

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

Демонстрация конъюнкции множеств П и У на картинках из интернетов

Используя эти операции мы можем работать с флагами:

var classWithFlags = new ClassWithFlags(); classWithFlags.Conditions |= ConditionsFlags.DoAnother;                               //Присвоение значения var hasClassDoAnother = (classWithFlags.Conditions & ConditionsFlags.DoAnother) != 0; //Чтение значения hasClassDoAnother = classWithFlags.Conditions.HasFlag(ConditionsFlags.DoAnother);     //Более привычное чтение

Как можно увидеть, работа с битовыми флагами является несколько нестандартной. Помимо этого неудобства, битовый флаг подразумевает, что состояние всегда определено и равно либо true, либо false, и не может быть равно null. Данная особенность может являться недостатком, поскольку порой постановка задачи может подразумевать, что состояние может быть неизвестно.

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

Приведение числа к enum

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

public class ClassWithEnumCast {     private const Colors TempColor = (Colors)int.MaxValue;      private readonly Colors[] _colorsOrder = { Colors.Red, TempColor, Colors.Black, Colors.White, Colors.Blue };      public IEnumerable GetOrder(Colors color)         => _colorsOrder.Select(x =>             x is TempColor                 ? color                 : x         ).Distinct();      public enum Colors     {         Red = 0,         Blue = 1,         White = 3,         Black = 4     } }

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

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

var color = (Colors)1;          //Blue var undefinedColor = (Colors)5; //5

Приведение одного enum к другому

Представим, что нам необходимо привести один enum к другому, например при маппинге одной структуры к другой. Как же поведет себя enum? Определим пару enum-ов и попробуем это сделать:

public enum Colors1 {     Red = 0,     Blue = 1 } public enum Colors2 {     White = 0,     Red = 1,     Blue = 2 }

В представленном примере мы создали два enum-а, один из которых обладает всеми значениями второго, но со смещенной из-за дополнительного значения нумерацией. Теперь попробуем привести первый enum ко второму:

var color = (Colors2)Colors1.Red;   //White

Но как же так, вроде же мы должны были получить значение Red, но получили White? Всё дело в том, что enum, как было сказано выше, является лишь именованным числом и приведение происходит именно по числовому значению. В случае необходимости подобного приведения потребуется написать дополнительный хелпер или явно описать каст через implicit/explicit.

public static Colors2 Cast(this Colors1 color)     => color switch     {         Colors1.Red => Colors2.Red,         Colors1.Blue => Colors2.Blue,         _ => Colors2.White     };

Бонусный контент

Подобный пример был создан на основе комментария с просторов Метанита. Предположим мы решим в край упороться и написать следующий enum (так делать не надо, пнятнеько):

enum Colors {     White,     Black = 0,     Blue = 3,     Green = 2,     Red }

А затем посмотреть как он будет себя вести:

var color1 = Colors.Black;  //White var color2 = Colors.Red;    //Blue

Что же за магия происходит в этом примере?

Поскольку у значения White явно не указано число, ему автоматически предоставляется число предыдущего значения +1, а поскольку это значение первое и перед ним ничего нет ему будет проставлено значение 0. Далее мы явно указываем для Black значение 0, что дублирует уже предоставленное значение для White. А поскольку White определено до Black, то и при обращении по значению 0 мы получим именно White.

В случае же color2, из-за описанной выше логики автопроставления чисел, значению Red было проставлено число 2+1=3. А при получении значения по числу вернулось первое в списке с таким числом.

Такие вот дела, ребята. А на сегодня всё.

Перечисление или java enum – это набор именованных констант, который помогает в определении своих собственных типов данных. Когда вы можете определить тип переменных в программе, становится легко их определить.

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

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

Объявление enum может быть сделано вне Класса или внутри Класса. Но мы не можем объявить Enum внутри метода. Давайте рассмотрим небольшой пример, чтобы понять его декларацию.

1. Объявление перечисления в Java вне класса

enum Directions{ // enum keyword is used instead of class keyword NORTH, SOUTH, EAST, WEST; } public class enumDeclaration { public static void main(String[] args) { Directions d1 = Directions.EAST; // new keyword is not required to create a new object reference System.out.println(d1); } }

Вывод:

EAST

2. Объявление перечисления в Java внутри класса

public class enumDeclaration { enum Directions{ NORTH, SOUTH, EAST, WEST; } public static void main(String[] args) { Directions d1 = Directions.EAST; // new keyword is not required to create a new object reference System.out.println(d1); } }

Вывод:

EAST

Первая строка внутри типа enum должна быть списком констант. Затем вы можете использовать методы, переменные и конструктор. По сути, enum представляет группу переменных и констант.

Замечания:

  • Enum в Java в основном улучшает безопасность типов.
  • Его можно по-разному использовать в примерах переключения.
  • Enum может быть легко пройден.
  • Перечисление имеет поля, конструкторы и методы.
  • Enum в основном реализует много интерфейсов, но не может расширять какой-либо класс, потому что он внутренне расширяет класс Enum.

Перечисление с использованием оператора Switch

Значение перечисления также может использоваться для управления оператором switch. Необходимо, чтобы все операторы case использовали константы из того же перечисления, что и оператор switch. Ниже пример демонстрирует то же самое.

package Edureka; import java.util.*; enum Directions { NORTH, SOUTH, EAST, WEST } public class Test1{ public static void main(String[] args) { Directions d= Directions.SOUTH; switch(d) { //The name of the enumertion constants are used without their enumeration case NORTH: //only constants defined under enum Directions can be used System.out.println("North direction"); break; case SOUTH: System.out.println("South direction"); break; case EAST: System.out.println("East directiion"); break; case WEST: System.out.println("West directiion"); break; }

Вывод:

South Direction

Values() и метод ValueOf()

Values(): при создании enum компилятор Java внутренне добавляет метод values(). Этот метод возвращает массив, содержащий все значения перечисления.

Синтаксис:

public static enum-type[ ] values()

ValueOf(): этот метод используется для возврата константы перечисления, значение которой равно строке, переданной в качестве аргумента при вызове этого метода.

Синтаксис:

public static enum-type valueOf (String str)

Теперь давайте напишем программу, чтобы понять эти методы более подробно.

enum Colors{ black, red blue, pink, white } class Test { public static void main(String args[]) { Colors c; System.out.println("All constants of enum type Colors are:"); Colors cArray[] = Colors.values(); //returns an array of constants of type Colors for(Colors a : cArray) //using foreach loop System.out.println(a); c = Colors.valueOf("red"); System.out.println("I Like" + c); } }

Вывод:

All constants of enum type Colors are: black red blue pink white I Like red

Вот как вы можете использовать метод Values(), чтобы вернуть массив, содержащий все перечисления, присутствующие в методе, и Valueof(), чтобы вернуть константу перечисления.

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

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

enum Student { mack(11), Birdie(10), Son(13), Victor(9); private int age; //variable defined in enum Student int getage { return age; } //method defined in enum Student public Student(int age) //constructor defined in enum { this.age= age; } } class EnumDemo { public static void main( String args[] ) { Student S; System.out.println("Age of Victor is " +Student.Victor.getage()+ "years"); } }

Вывод:

Age of Victor is 9 years

Здесь, как только мы объявляем переменную enum(), конструктор вызывается один раз, и он инициализирует параметр age для каждой константы перечисления значениями, указанными в скобках.

Что нужно знать?

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

public enum Currency {  PENNY, NICKLE, DIME, QUARTER };  Currency coin = Currency.PENNY;  coin = 1; //compilation error

2). Enum в Java – это ссылочные типы, такие как класс или интерфейс, и вы можете определить конструктор, методы и переменные внутри, что делает его более мощным, чем Enum в C и C ++, как показано в следующем примере.

3). Вы можете указать значения констант перечисления во время создания, как показано в примере ниже:

public enum Currency {PENNY(1), NICKLE(5), DIME(10), QUARTER(25)};

Но для этого вам необходимо определить переменную-член и конструктор, потому что PENNY (1) фактически вызывает конструктор, который принимает значение int, см. Пример ниже.

public enum Currency {  PENNY(1), NICKLE(5), DIME(10), QUARTER(25);  private int value;  private Currency(int value) {  this.value = value; } };

Конструктор должен быть закрытым, любой другой модификатор доступа приведет к ошибке компиляции. Теперь, чтобы получить значение, связанное с каждой монетой, вы можете определить общедоступный метод getValue() внутри перечисления Java, как любой обычный класс. Кроме того, точка с запятой в первой строке не обязательна.

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

Currency.PENNY = Currency.DIME;

Последнее поле EnumExamples.Currency.PENNY нельзя переназначить.

5) Может использоваться в качестве аргумента в операторе switch и с «case:», например, с примитивным типом int или char. Эта особенность делает их очень полезными для операций переключения. Давайте посмотрим, как использовать enum внутри оператора switch:

Currency usCoin = Currency.DIME;     switch (usCoin) {             case PENNY:                     System.out.println("Penny coin");                     break;             case NICKLE:                     System.out.println("Nickle coin");                     break;             case DIME:                     System.out.println("Dime coin");                     break;             case QUARTER:                     System.out.println("Quarter coin");  }

Поскольку константы, определенные внутри Enum, являются окончательными, вы можете безопасно сравнивать их, используя «==», оператор равенства, как показано в следующем примере:

Currency usCoin = Currency.DIME;  if(usCoin == Currency.DIME){  System.out.println("enum in java can be compared using ==");  }

Сравнение объектов с использованием оператора == не рекомендуется. Всегда используйте метод equals() или compareTo() для сравнения объектов.

7). Компилятор Java автоматически генерирует метод static values() для каждого перечисления. Метод Values() возвращает массив констант Enum в том же порядке, в котором они перечислены, и вы можете использовать values() для перебора значений, как показано в примере ниже:

for(Currency coin: Currency.values()){    System.out.println("coin: " + coin); }  And it will print: coin: PENNY coin: NICKLE coin: DIME coin: QUARTER

8). Он также может переопределять методы. Давайте посмотрим на пример переопределения метода toString() внутри Enum, чтобы предоставить содержательное описание для констант перечислений.

public enum Currency {   ........          @Override   public String toString() {        switch (this) {          case PENNY:               System.out.println("Penny: " + value);               break;          case NICKLE:               System.out.println("Nickle: " + value);               break;          case DIME:               System.out.println("Dime: " + value);               break;          case QUARTER:               System.out.println("Quarter: " + value);         }   return super.toString();  } };

А вот как это выглядит при отображении:

Currency usCoin = Currency.DIME; System.out.println(usCoin);  Output: Dime: 10

9). Два новых класса коллекции EnumMap и EnumSet добавлены в пакет коллекции для поддержки. Эти классы представляют собой высокопроизводительную реализацию интерфейса Map and Set в Java, и мы должны использовать их всякий раз, когда есть возможность.

EnumSet не имеет общедоступного конструктора, вместо этого он предоставляет фабричные методы для создания экземпляра, например. EnumSet.of() методы. Этот дизайн позволяет EnumSet внутренне выбирать между двумя различными реализациями в зависимости от размера констант.

Если Enum имеет менее 64 констант, чем EnumSet использует класс RegularEnumSet, который внутренне использует длинную переменную для хранения этих 64 констант, а если Enum имеет больше ключей, чем 64, то он использует JumboEnumSet.

10). Вы не можете создать экземпляр перечислений с помощью оператора new в Java, потому что конструктор может быть только частным, а константы Enums могут быть созданы только внутри него самого.

11). Экземпляр создается, когда какие-либо константы Enum сначала вызываются или упоминаются в коде.

12). Может реализовать интерфейс и переопределить любой метод, такой как обычный класс. Также стоит отметить, что Enum в Java неявно реализует как Serializable, так и Comparable интерфейс. Давайте посмотрим и пример того, как реализовать интерфейс:

public enum Currency implements Runnable{   PENNY(1), NICKLE(5), DIME(10), QUARTER(25);   private int value;   ............            @Override   public void run() {   System.out.println("Enum in Java implement interfaces");                     } }

13). Вы можете определить абстрактные методы внутри Enum, а также можете предоставить другую реализацию для разных экземпляров. Давайте посмотрим на пример использования абстрактного метода внутри.

  public enum Currency {         PENNY(1) {             @Override             public String color() {                 return "copper";             }         },         NICKLE(5) {             @Override             public String color() {                 return "bronze";             }         },         DIME(10) {             @Override             public String color() {                 return "silver";             }         },         QUARTER(25) {             @Override             public String color() {                 return "silver";             }         };         private int value;          public abstract String color();          private Currency(int value) {             this.value = value;         }   }     

В этом примере, поскольку каждая монета будет иметь разный цвет, мы сделали метод color() абстрактным и позволили каждому экземпляру Enum определять свой собственный цвет. Вы можете получить цвет любой монеты, просто вызвав метод color(), как показано в примере ниже:

System.out.println("Color: " + Currency.DIME.color());

Видим, что вы не нашли ответ на свой вопрос.

Помогите улучшить статью.

Напишите комментарий, что можно добавить к статье, какой информации не хватает.

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

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

Enum примитивный перечисляемый тип¶

Enum — это конструкция, состоящая из набора именованных констант, именуемая списком перечисления и определяемая такими примитивными типами, как number и string. Enum объявляется с помощью ключевого слова enum.

Перечисления с числовым значением¶

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

 enum Fruits {   Apple, // 0   Pear, // 1   Banana, // 2  }  

Также можно установить любое значение вручную.

 enum Citrus {   Lemon = 2, // 2   Orange = 4, // 4   Lime = 6, // 6  }  

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

 enum Berrys {   Strawberry = 1,   Raspberry, // 2    Blueberry = 4,   Cowberry, // 5  }  

Компилятор рассчитывает значение автоматически только на основе значения предыдущего члена перечисления. То есть, если первой и третьей константе было установленно значение 10 и 20.

 enum Keys {   A = 10,   B, // 11   C = 20,   D, // 21  }  

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

 enum Keys {   A = 10,   B, // 11   C = 10,   D, // 11  }  

Вдобавок ко всему enum позволяет задавать псевдонимы (alias). Псевдонимам устанавливается значение константы, на которую они ссылаются.

 enum Langues {   Apple, // en, value = 0   Apfel = Apple, // de, value = 0   LaPomme = Apple, // fr, value = 0  }  

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

 let value: number = Fruits.Apple; // 0  let identificator: string = Fruits[value]; // “Apple”  

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

1 шаг. Тем, кто ранее работал с enum, уже известно, что он позволяет получать строковое представление константы, а также значение, ассоциированное с ней. Поэтому для его создания требуется ассоциативный массив, коими в JavaScript являются объекты. Назовем объект Fruits и передадим его в качестве аргумента в функцию initialization, которая будет содержать код его инициализации.

 let Fruits = {};   function initialization(Fruits) {}  

2 шаг. Создадим поле с именем Apple и присвоим ему в качестве значения число .

 let Fruits = {};   function initialization(Fruits) {   Fruits['Apple'] = 0;  }  

3 шаг. Ассоциация константа-значение произведена, осталось создать зеркальную ассоциацию значение-константа. Для этого создадим ещё одно поле, у которого в качестве ключа будет выступать значение , а в качестве значения — строковое представление константы, то есть имя.

 let Fruits = {};   function initialization(Fruits) {   Fruits['Apple'] = 0;   Fruits[0] = 'Apple';  }  

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

 let Fruits = {};   function initialization(Fruits) {   let value = (Fruits['Apple'] = 0); // то же самое что value = 0   Fruits[value] = 'Apple'; // то же самое что Fruits[0] = "Apple";  }  

5 шаг. Продолжим сокращать и в первом выражении откажемся от переменной value, а во втором выражении на её место поместим первое выражение.

 let Fruits = {};   function initialization(Fruits) {   Fruits[(Fruits['Apple'] = 0)] = 'Apple';  }  

6 шаг. Теперь проделаем то же самое для двух других констант.

 let Fruits = {};   function initialization(Fruits) {   Fruits[(Fruits['Apple'] = 0)] = 'Apple';   Fruits[(Fruits['Lemon'] = 1)] = 'Lemon';   Fruits[(Fruits['Orange'] = 2)] = 'Orange';  }  

7 шаг. Теперь превратим функцию intialization в самовызывающееся функциональное выражение и лучше анонимное.

 let Fruits = {};   (function (Fruits) {   Fruits[(Fruits['Apple'] = 0)] = 'Apple';   Fruits[(Fruits['Pear'] = 1)] = 'Pear';   Fruits[(Fruits['Banana'] = 2)] = 'Banana';  })(Fruits);  

8 шаг. И перенесем инициализацию объекта прямо на место вызова.

 let Fruits;  (function (Fruits) {   Fruits[(Fruits['Apple'] = 0)] = 'Apple';   Fruits[(Fruits['Pear'] = 1)] = 'Pear';   Fruits[(Fruits['Banana'] = 2)] = 'Banana';  })(Fruits || (Fruits = {}));  

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

 // enum сгенерированный typescript compiler  let Fruits;  (function (Fruits) {   Fruits[(Fruits['Apple'] = 0)] = 'Apple';   Fruits[(Fruits['Pear'] = 1)] = 'Pear';   Fruits[(Fruits['Banana'] = 2)] = 'Banana';  })(Fruits || (Fruits = {}));  

Теперь добавим в рассматриваемое перечисление псевдоним LaPomme (яблоко на французском языке) для константы Apple.

 enum Fruits {   Apple, // 0   Pear, // 1   Banana, // 2    LaPomme = Apple, // 0  }  

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

 (function (Fruits) {   Fruits[(Fruits['Apple'] = 0)] = 'Apple';   Fruits[(Fruits['Lemon'] = 1)] = 'Lemon';   Fruits[(Fruits['Ornge'] = 2)] = 'Ornge';   Fruits[(Fruits['LaPomme'] = 0)] = 'LaPomme'; // псевдоним  })(Fruits || (Fruits = {}));  

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

Помимо значения, принадлежащего к типу number, TypeScript позволяет указывать значения с типом string.

 enum FruitColors {   Red = '#ff0000',   Green = '#00ff00',   Blue = '#0000ff',  }  

Но в случае, когда константам присваиваются строки, ассоциируется только ключ со значением. Обратная ассоциация (значение-ключ) — отсутствует. Простыми словами, по идентификатору (имени константы) можно получить строковое значение, но по строковому значению получить идентификатор (имя константы) невозможно.

 var FruitColors;  (function (FruitColors) {   FruitColors['Red'] = '#ff0000';   FruitColors['Green'] = '#00ff00';   FruitColors['Blue'] = '#0000ff';  })(FruitColors || (FruitColors = {}));  

тем не менее остается возможность создавать псевдонимы (alias).

 enum FruitColors {   Red = '#ff0000',   Green = '#00ff00',   Blue = '#0000ff',    Rouge = Red, // fr "#ff0000"   Vert = Green, // fr "#00ff00"   Bleu = Blue, // fr "#0000ff"  }  

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

 var FruitColors;  (function (FruitColors) {   FruitColors['Red'] = '#ff0000';   FruitColors['Green'] = '#00ff00';   FruitColors['Blue'] = '#0000ff';   FruitColors['Rouge'] = '#ff0000';   FruitColors['Vert'] = '#00ff00';   FruitColors['Bleu'] = '#0000ff';  })(FruitColors || (FruitColors = {}));  

Смешанное перечисление¶

Если в одном перечислении объявлены числовые и строковые константы, то такое перечисление называется смешанным (mixed enum).

Со смешанным перечислением связаны две неочевидные особенности.

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

 enum Stones {   Peach, // 0   Apricot = 'apricot',  }  

Вторая особенность заключается в том, что если константа, которой значение не было присвоено явно, следует после константы со строковым значением, то такой код не скомпилируется. Причина заключается в том, что как было рассказано в секции Перечисления с числовым значением, если константе значение не было установлено явно, то её значение будет рассчитано, как значение предшествующей ей константе +1, либо , в случае её отсутствия. А так как у предшествующей константы значение принадлежит к строковому типу, то рассчитать число на его основе не представляется возможным.

 enum Stones {   Peach, // 0   Apricot = 'apricot',   Cherry, // Error   Plum, // Error  }  

Для разрешения этой проблемы в смешанном перечислении, константе, которая была объявлена после константы со строковым значением, необходимо задавать значение явно.

 enum Stones {   Peach, // 0   Apricot = 'apricot',   Cherry = 1, // 1   Plum, // 2  }  

Перечисление в качестве типа данных¶

Может возникнуть мысль использовать перечисление в качестве типа данных переменной или параметра. Это вполне нормальное желание, но нужно быть очень осторожным: в TypeScript с перечислением связан один достаточно неприятный нюанс. Дело в том, что пока в перечислении есть хотя бы одна константа с числовым значением, он будет совместим с типом number. Простыми словами, любое число проходит проверку совместимости типов с любым перечислением.

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

 enum Fruits {   Apple,   Pear,   Banana = 'banana',  }   function isFruitInStore(fruit: Fruits): boolean {   return true;  }   isFruitInStore(Fruits.Banana); // ок  isFruitInStore(123456); // ок  isFruitInStore('banana'); // Error  

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

 enum Berrys {   Strawberry = 'strawberry',   Raspberry = 'raspberry',   Blueberry = 'blueberry',  }   function isBerryInStory(berry: Berrys): boolean {   return true;  }   isBerryInStory(Berrys.Strawberry); // ок  isBerryInStory(123456); // Error  isBerryInStory('strawberry'); // Error  

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

Перечисление const с числовым и строковым значением¶

Перечисление enum, объявленное с помощью ключевого слова const, после компиляции не оставляет в коде привычных конструкций. Вместо этого компилятор встраивает литералы значений в места, в которых происходит обращение к значениям перечисления. Значения констант перечисления могут быть как числовыми, так и строковыми типами данных. Также как и в обычных перечислениях, в перечислениях, объявленных с помощью ключевого слова const есть возможность создавать псевдонимы (alias) для уже объявленных констант.

Если создать два перечисления Apple и Pear, у каждого из которых будет объявлена константа Sugar с числовым значением, то на основе этих констант можно рассчитать количество сахара в яблочно-грушевом соке. Присвоив результат операции сложения количества сахара в промежуточную переменную, мы получим хорошо читаемое, задекларированное выражение.

 const enum Apple {   Sugar = 10,  }   const enum Pear {   Sugar = 10,  }   let calciumInApplePearJuice: number =   Apple.Sugar + Pear.Sugar;  

После компиляции от перечисления не остается и следа, так как константы будут заменены числовыми литералами. Такое поведение называется inline встраивание.

 let calciumInApplePearJuice = 10 + 10;  

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

Тип enum является уникальным для TypeScript, в JavaScript подобного типа не существует.

Когда стоит применять enum?¶

Может возникнуть вопрос – “Когда использовать enum и стоит ли это делать с учетом закрепившейся привычки работы со статическими классами и константами?”.

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

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

Ну а тем кто считает, что скомпилированная конструкция enum отягощает их код и при этом они пользовались ранее транскомпилятором Babel, то ответьте себе на вопрос – Почему вы это делали, если он добавляет в сотню раз больше лишнего кода?. Рассуждение о том, что несколько лишних строк кода испортит или опорочит программу, является пустой тратой драгоценного времени.

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

Оцените статью
Рейтинг автора
4,8
Материал подготовил
Максим Коновалов
Наш эксперт
Написано статей
127
А как считаете Вы?
Напишите в комментариях, что вы думаете – согласны
ли со статьей или есть что добавить?
Добавить комментарий