Как стать автором
Обновить

Комментарии 23

к сожалению, Enum становится больше похожим на полноценный класс.

в Java это не считается проблемой уже много лет )

А чем это плохо?

Излишняя зона ответственности. Енам же изначально — это просто обычный скалярный int с ограничениями по значениям и псевдонимами. То что уже в него впихнули в RFC (https://wiki.php.net/rfc/enumerations), имхо, уже и так избыточно.

А PHP — изначально шаблонизатор, это понятно.

Вот в Енамы добавили по сути константы и методы — можно пример, когда это плохо?

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


Избыточность функционала необратимо приведёт к куче реализаций GOD-перечислений, так же как сейчас куча GOD-классов, где один инстанс "и жрец, и жнец, и на дуде игрец" (взять хотя бы Eloquent в ларке, где по одному классу модельки уже можно бенчмаркать редактор в PhpStorm).


Ну и с другой стороны посмотреть, зачем нужны вообще тогда эти новые енамы, когда есть классы, где есть и так все возможности енамов? Только ради типизации?


Если подытожить — получаем более тяжёлую и монструозную бандуру против более легких и быстрых констант в классах. У меня, в общем, крайне противоречивое впечатление от них. Надо на практике посмотреть насколько они больше будут кушать и насколько более тормознуто работать по сравнению с обычными константами.

От Larry Garfield ничего кроме переусложней и ждать не приходится, только теперь начал понимать Fabien'а почему он ушел из PSR увидев творения Larry.

Но судя по голосованию, большинство имеющих право голоса поддержали это нововведение. Хотя вот это вот расширение enum до класса меня лично вводит в недоумение. Интересно, будет ли это пользоваться успехом на практике.

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

синглтоны же

Вот в Енамы добавили по сути константы и методы

Вот, сейчас попробовал на практике и поигрался с ними (актуальный dev билд с мастера). Константы говоришь? Ох если бы...


1) Проблема первая. Неудобство использования.


Предлагаю угадать с первого раза какой будет результат у этого кода:


enum Method: string
{
    case Get = 'GET';
    case Post = 'POST';
    case Put = 'PUT';
    // ...
}

echo Method::Get;

Если кто-то думает что string(3) "GET", то он глубоко ошибается. Будет ошибка, т.к. enum value — это объект без реализации __toString или других "магических" перегрузок к типу.


2) Невозможность self-ссылок


enum VkStructureType: int
{
    // Один из кейсов VkStructureType
    case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES                      = 1000120000;

    // Алиас
    case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES                       = self::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES;
}

Ошибка: "Enum case type \VkStructureType does not match enum backing type int".
Ссылка на value тоже невозможна: "Enum case value must be constant".


Вот это вообще жесть.


3) Дублирование значений тоже недопустимо. Т.е. такие кейсы как опечатка в значении в пакете и патч, делающий алиас на это имя невозможны в принципе. Например, как в этом случае: https://github.com/teapot-php/status-code/blob/7aaba4364645ebb9d3a36267c9b3a32206d3042b/src/RFC/RFC7231.php#L222


4) Потребление памяти. Тестовый скрипт:


$usage = \memory_get_usage();
require __DIR__ . '/VkStructureType.php';
echo \memory_get_usage() - $usage;

  • Классический вариант PHP 8.1 с class + const: 96 bytes
  • Новые енамы PHP 8.1 с enum: 107288 bytes

Т.е. примерно в 1118 раз больше весит!

enum value — это объект

Логично. А иначе он как бы через type hints проходил?


Невозможность self-ссылок

Там ведь константу можно с общим значением добавить? Вроде как эта проблема вытекает из реализации значений как объектов.


Дублирование значений тоже недопустимо.

Тогда бы ведь сломалось получение enum item по значению.

1) Про первый пункт в RFC явно написано wiki.php.net/rfc/enumerations#auto-scalar_conversion

Whether or not a Backed Enum can be viewed as “close enough” to its corresponding scalar value is debatable, and of debatable value. For instance, is a string-backed enum Stringable? Should an int type check accept an int-backed enum value? Should a string-backed enum work in a print statement? What about up-converting a scalar to its corresponding enum automatically?

The optimal behavior here, if any, will likely not become apparent until enums see widespread use. We have therefore opted to omit all auto-conversion at this time. If clear and compelling use cases for auto-conversion appear in the future, later PHP versions can re-introduce such auto-conversion in a more targeted, well-informed way.


2) 3) Согласен, тут не оч удобно сделано.

Воркэраунд, который предлагают это через константу:

enum Method: string
{
   
    case Get = 'GET';
    case Post = 'POST';
    case Put = 'PUT';
    
    const Post2 = self::Post;
}

function foo(Method $method) { 
    var_dump($method); 
};

foo(Method::Post2);
3v4l.org/nESt8/rfc#git.master

4) Давай весь скрипт в студию.
НЛО прилетело и опубликовало эту надпись здесь
Авторы енамов провели целое исследование прежде чем предложить RFC. Вот тут сводная таблица по языкам github.com/Crell/enum-comparison#summary.

Вот так можно сгруппировать их:
Fancy Constants: C, Typescript, F#
Fancy Objects: Python, Java, C#, Scala
Algebraic Data Types: Haskell, Swift, Rust, Kotlin

Ну и собственно PHP вдохновлен третьей группой.

В статье F# union types не в ту группу положили, он в F# относится к Algebraic Data Types, ну а enum к Fancy Objects. А PHP никак в трелью группу не попадет, на ADT Union легко можно древесные структуры или AST представить.

Это по сути ведь тип сумма разнородных типов данных со структурной меткой над ними. Самое то для моделирования предметной области.

Это плохо тем, что enum может иметь внутреннее состояние. То есть по сути такая реализация — это просто singleton object.
От enum я жду, что это будет набор именованных значений сгруппированных по смыслу. От методов enum я жду, что они будут возвращать либо одно из значений enum, либо массив значений, либо null, либо кидать исключение. Сейчас оттуда можно вернуть что угодно.
А такие вещи как трейты, наследование, публичные константы только переусложняют и запутывают.

а почему его действительно не сделать полноценным классом с имплементацией какого нибудь интерфейса.

Flarum 1.0.0 — Релиз популярного движка для форума на PHP.


не прошло и 5 лет )

array_map(Something::toString(?), [1, 2, 3]);


Здесь знак вопроса — точно не опечатка?

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

P.S. Ой, извиняюсь, я не понял вопроса вначале.

Поправил, спасибо!
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории