Автор оригинала: David Wong.
Статья была переслана из профессионального сообщества разработчиков laravel. Оригинальная ссылка: https://learnku.com/laravel/t
Эта статья направлена на то, чтобы лучше понять, что такое перечисления, когда их использовать и как их использовать в PHP
Иногда мы используем константы для определения некоторых постоянных значений в коде. Они используются, чтобы избежать магических значений. Мы можем придать ему некоторый смысл, заменив некоторые магические значения символическим именем. Затем мы ссылаемся на название символа в коде. Поскольку мы определяем его один раз и используем много раз, его легче найти и переименовать или изменить значение позже
Вот почему нередко можно увидеть такой код
Вышеуказанные константы представляют два набора свойств, пол? А статус? Соответственно. Они представляют собой набор пола и набор статуса пользователя. Каждая группа представляет собой перечисление. Перечисление-это набор элементов (также называемых членами), каждый из которых определяет новый тип. Этот тип, как и его значение, может содержать любой элемент, принадлежащий перечислению.
В приведенном выше примере перечисление использует константы, и значение каждой константы является членом. Обратите внимание, что при этом мы можем принимать значения только того типа, который содержит константа. Поэтому, когда мы записываем эти значения, у нас не будет запроса типа и мы не знаем подробного типа перечисления.
Давайте рассмотрим короткий пример, но давайте предположим, что в этом примере больше кода
create(
$email,
User::STATUS_ACTIVE,
User::GENDER_FEMALE
);На первый взгляд код выглядит хорошо, но так уж получилось, что он работает правильно! Поскольку два разных элемента перечисления на самом деле имеют одно и то же значение, вызов метода создания выполняется успешно, поскольку два последних параметра меняются местами, не влияя на результат. Хотя мы проверяем, является ли значение, принятое методом, допустимым, интерфейс среды выполнения не предупредит нас, и тест пройдет. Некоторые люди могут правильно найти эти ошибки, но это также может быть проигнорировано. В более поздних случаях, например при объединении конфликтов, если его значение изменится, это может привести к системным исключениям.
Если мы используем скалярный тип, мы будем ограничены этим типом, мы не можем сказать, принадлежат ли эти два значения двум разным перечислениям.
Другая проблема заключается в том, что код не очень хорош. Представьте, что метод create не ссылается на константу. $пол Насколько трудно будет восприниматься другими как элемент перечисления? Насколько сложно понять, где определены эти элементы? Мы прочитаем этот код позже, поэтому мы должны сделать его как можно более легким для чтения и передачи.
Можем ли мы сделать лучше? Конечно! Этот метод заключается в использовании экземпляра класса в качестве элемента перечисления, а сам класс определяет новый тип. До PHP 7 мы могли установить расширение PECL класса SPL и использовать plenum.
Мы расширяем СплЕнум И определите константы для создания элементов перечисления. Элементы перечисления-это объекты, которые мы создаем вручную, в данном случае само постоянное значение. Может показаться странным, что мы можем сравнивать целые числа с объектами. Кроме того, как указано в документации, это перечисление симуляций. Сам PHP не поддерживает типы перечисления, поэтому все, о чем мы здесь говорим, моделируется.
Что мы получаем таким образом? Мы можем ввести параметры, которые запрашивают нас, и пусть движок PHP напоминает нам, когда возникает ошибка. Мы также можем включить некоторую логику в класс перечисления и использовать оператор switch для моделирования полиморфного поведения.
Но есть и некоторые недостатки. Например, в большинстве случаев вместо проверки подлинности можно использовать элементы перечисления. Это не невозможно, мы должны быть очень осторожны. Поскольку мы создаем элементы перечисления вручную, многие элементы должны быть одним и тем же элементом, но это трудно определить вручную
Утилизация СплЕнум Мы решаем проблему с типом перечисления, но мы должны быть очень осторожны при проверке подлинности. Нам нужен метод, позволяющий ограничить количество элементов, которые могут быть созданы, например, несколько одноэлементных объектов
Теперь мы увидим, что Java enum вдохновлен и реализован многотонный Две разные библиотеки
Первый-красноречивый/перечислительный. Он создает экземпляр класса определения для каждого элемента. Пожалуйста, обратите внимание, что без нашей помощи моделирование пользователей перечисления никогда не сможет гарантировать экземпляр перечисления, потому что у нас есть способ избежать ограничения каждого его шага
Эта библиотека может позволить нам неправильно попытаться, например, создать экземпляр с отражением. На этом этапе мы можем спросить себя, правильно ли мы поступили. Это также может помочь в процессе проверки кода, поскольку такая реализация может определить несколько правил, которым следует следовать. Если эти правила относительно просты, то в коде легко найти проблемы
Давайте рассмотрим несколько примеров
key()); // YES
Мы определяем наследование \Красноречивое\Перечисление\Абстрактное перечисление Новый класс Да, Затем мы определяем константу, которая определяет имя элемента и создает библиотеку объектов, представляющих эти элементы
Есть и другие ситуации, которые нам нужно иметь в виду сериализация /| десериализация Создание в нем пользовательского объекта
Мы можем найти больше примеров и полных документов на странице GitHub.
Вторая библиотека, которую мы хотим показать, – это zlikavac32/PHP перечисление красноречивое/перечисление В отличие от этого, эта библиотека предназначена для абстрактных классов, которые допускают истинное полиморфное поведение. Поэтому вместо использования метода switch . Определяя перечисления со строгими правилами, вы также можете быть достаточно надежными в обеспечении того, чтобы каждый элемент имел только один экземпляр.
Эта библиотека ориентирована на абстрактные классы, чтобы ограничить количество экземпляров каждого члена одним. Идея состоит в том, что каждое перечисление должно быть определено как абстрактное и перечислять его элементы. Пожалуйста, обратите внимание, что вы можете злоупотреблять этим, расширяя класс, а затем создавая элемент, но если вы это сделаете, они будут выделены в процессе проверки кода.
Для абстрактных классов мы знаем, что у нас не случайно есть новый элемент перечисления, потому что он требует конкретной реализации. Следуя правилам, которые содержат эти конкретные реализации в самом перечислении, мы можем легко обнаружить злоупотребления. Здесь полезны анонимные классы.
Библиотека создает абстрактный класс перечисления, но не может принудительно создать допустимый элемент. Ответственность за это несут пользователи данной библиотеки. Об остальном позаботится библиотека.
Давайте рассмотрим простой пример.
name()); // YES
Аннотация phpdoc определяет существующие статические методы, возвращающие элементы перечисления. Это помогает осуществлять поиск и рефакторинг кода. Далее мы перечислим Да Нет Определено как абстрактное и расширенное \Zlikavac32\Перечисление\Перечисление И определите статический метод перечислить 。 Затем в методе перечислить мы перечисляем имена элементов, которые будут использоваться для их представления.
Мы только что упомянули полиморфизм, так зачем же мы его используем? Одна вещь, которая происходит, когда мы пытаемся ограничить несколько экземпляров одного и того же элемента перечисления, заключается в том, что у нас не может быть циклических ссылок. Давайте представим, что мы хотим иметь СЕВЕР , ЮГ , ВОСТОК и ЗАПАД Составлено По всему миру Перечисление. Мы также хотим иметь способ противоположный():Мировая сторона , который возвращает элемент, представляющий противоположное. Если мы попытаемся ввести противоположный элемент через конструктор, в какой-то момент мы получим круговую ссылку, что означает, что нам нужен второй экземпляр того же элемента. Чтобы вернуть действительный противоположный мир, мы должны использовать прокси-объект или переключатель Крушение предложений.
С помощью полиморфизма все, что мы можем сделать, это показать нам, что мы можем определить, что нам нужно По всему миру Перечисление.
new class extends WorldSide {
public function opposite(): WorldSide {
return WorldSide::SOUTH();
}
},
'SOUTH' => new class extends WorldSide {
public function opposite(): WorldSide {
return WorldSide::NORTH();
}
},
'EAST' => new class extends WorldSide {
public function opposite(): WorldSide {
return WorldSide::WEST();
}
},
'WEST' => new class extends WorldSide {
public function opposite(): WorldSide {
return WorldSide::EAST();
}
}
];
}
abstract public function opposite(): WorldSide;
}
foreach (WorldSide::iterator() as $worldSide) {
var_dump(sprintf(
'Opposite of %s is %s',
(string) $worldSide,
(string) $worldSide->opposite()
));
}оставайтесь перечислять Метод, мы обеспечиваем реализацию каждого элемента перечисления. Массивы индексируются по именам элементов перечисления. При создании элементов вручную мы определяем имя нашего элемента как ключ данных.
Мы можем использовать Worldwide::iterator() Получает итератор порядка элементов перечисления для их определения и обхода. Каждый элемент перечисления имеет значение по умолчанию __toString(): Реализация string возвращает имя элемента.
Каждый элемент перечисления возвращает свой противоположный элемент.
Напомним, что константы не являются перечислениями, а перечисления не являются константами. Каждое перечисление определяет тип. Если у нас есть какие-то константы, значения которых важны для нас, но имена которых нет, мы должны придерживаться констант. Если у нас есть постоянные значения, которые для нас не имеют значения, но отличаются от всех остальных в той же группе, важно использовать перечисление
Перечисления обеспечивают больший контекст для кода, и некоторые проверки могут быть делегированы самому движку. Если PHP поддерживает локальное перечисление, это будет очень хорошо. Изменения синтаксиса могут сделать код более читабельным. Механизм может выполнять проверки для нас и выполнять правила, которые не могут быть выполнены из области пользователя.
Как вы используете перечисления и что вы думаете об этой теме? Пожалуйста, прокомментируйте ниже
Оригинал: “https://developpaper.com/how-do-you-handle-enum-in-php-code/”