Русский
Русский
English
Статистика
Реклама

Enum в PHP 8.1 для чего нужен enum, и как реализован в PHP

Через несколько дней заканчивается голосование по первой итерации реализации enum в PHP 8.1 . Уже видно, что голосов за гораздо больше, так что давайте кратко пройдемся и посмотрим, что же нам приготовили авторы языка.


Зачем нужны enum?


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


class Car {    private string $color;    function setColor(string $color): void {        $this->color = $color;    }}

Если мы опишем цвет машины как простой string, то во-первых при вызове $myCar->setColor(..) непонятно, что за строку туда писать. red или RED или #ff0000, а во вторых, легко ошибиться, просунув туда случайно что-то не то (пустую строку, к примеру). То же самое будет, если использовать не строки, а числа, например.


Это приводит к тому, что многие php-программисты заводят константы и объединяют их в одном классе, чтобы явно видеть все варианты.


class Color {    public const RED   = "red";    public const BLACK = "black";    public const WHITE = "white";}

и задавая цвет, пишут $myCar->setColor(Color::RED);


Уже лучше. Но если мы впервые видим метод $myCar->setColor(...), мы можем и не знать, что где-то есть константы для цветов. И мы всё еще можем сунуть туда любую строку без какого-либо сообщения об ошибке.


Поэтому здесь нужен не класс, а отдельный тип. Этот тип называется enum


Pure enum


В самом простом случае (pure enum), enum описывается так:


enum Color {    case Red;    case Black;    case White;}

Описав такой тип, мы можем использовать его везде:


class Car {    private Color $color;    function setColor(Color $color): void {        $this->color = $color;    }}

Из сигнатуры метода всё сразу видно, какие варианты есть. И метод setColor можно использовать только так: $myCar->setColor(Color::White), никаких строк и доморощенных списков констант. Ничего лишнего не сунешь. Читабельность и поддерживаемость кода стала выше.


Каждый из case-ов (Color::Red, Color::Black, Color::White) является объектом типа Color (можно проверить через instanseof ). Т.е. под капотом это не числа 0,1,2 как в некоторых языках, а именно объекты. Их нельзя сравнивать оператором >, например. У каждого такого объекта есть встроенное свойство $name:


print Color::Red->name; // вернет строку Red

Enum со скалярами


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


enum Color: string {    case Red = "R";    case Black = "B";    case White = "W";}

Скалярное значение можно получить потом так:


Color::Red->value  //вернет строку R

И наоборот, т.е. получить case через значение, тоже можно:


Color::from("R") // вернет объект Color::Red

Помимо полей "case" в enum может быть еще много всего. По сути это разновидность класса. Там могут быть методы, он может реализовывать интерфейсы или использовать трейты.


Пример из RFC.


interface Colorful {  public function color(): string;}trait Rectangle {  public function shape(): string {    return "Rectangle";  }}enum Suit implements Colorful {  use Rectangle;  case Hearts;  case Diamonds;  case Clubs;  case Spades;  public function color(): string {    return match($this) {      Suit::Hearts, Suit::Diamonds => 'Red',      Suit::Clubs, Suit::Spaces => 'Black',    };  }}

При этом $this будет тот конкретный объект case, для которого мы вызываем метод.


Кстати, обратите внимание на работу с енамами в конструкции match. Похоже, match затевался именно для них.


Лично я горячо одобряю введение enum в PHP, это очень удобно и читабельно, и в большинстве языков, где есть какие-никакие типы, enum уже давно есть (кроме, разве что Go).


Дальше больше. Tagged Unions (тип-сумма)


Есть RFC, которые развивают идею enums дальше, чтобы можно было хранить в одном enum значения разных типов. Как в языке Rust, например. Тогда можно будет сделать, допустим, enum Result с двумя case-ами Result::Ok и Result::Err, причем эти объекты будут хранить данные: Ok будет хранить результат, а Err ошибку, у каждого из этих значений будет свой тип.


И всё это не в Расте или Хаскеле, а в PHP!


Об этом мы расскажем в деталях в ближайших постах телеграм-канала Cross Join, не забудьте подписаться.

Источник: habr.com
К списку статей
Опубликовано: 07.02.2021 18:17:06
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Разработка веб-сайтов

Php

Программирование

Enum

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru