Подсказка типа с перечислениями?

Я читал здесь о перечислениях и их реализации

PHP и перечисления

Дело в том, зачем использовать перечисления, если не для подсказки типа?

но эта реализация не позволяет использовать подсказку типа. Поскольку все записи перечисления являются строками.

есть способ сказать

function($a) {

}

$a должно быть 'foo', 'bar' или 'baz'

в PHP?

Я использую phpstorm/intellij, поэтому, если есть другой способ сделать это, это тоже будет хорошо. Например. скажем в документе, но с магией автозаполнения от phpstorm, или, может быть, с ошибками компиляции.


person Toskan    schedule 07.05.2016    source источник


Ответы (2)


В PHP нет встроенного способа потребовать, чтобы переданная строка имела определенное значение; даже не в PHP7. Вы можете указывать объекты и массивы, о которых я знаю. Перечисления могли бы решить эту проблему, но PHP не поддерживает перечисления.

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

Если вы застряли с PHP

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

Попробуйте это

<?php

class WeekDay {
    private $value;

    public function __construct($value) {
        if (!in_array($value, ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday']))
            throw new Exception("Not a week day.");
        else
            $this->value = $value;
    }

    public function __toString() {
        return $this->value;
    }
}

function echoWeekDay(WeekDay $weekDay) {
    echo $weekDay . "\n";
}

echoWeekDay(new WeekDay("Tuesday"));
echoWeekDay(new WeekDay("Saturday"));

Бегите с

~/Code/stack-overflow $ php enums.php
Tuesday
PHP Fatal error:  Uncaught exception 'Exception' with message 'Not a week day.' in /Users/marianol/Code/stack-overflow/enums.php:8
Stack trace:
#0 /Users/marianol/Code/stack-overflow/enums.php(23): WeekDay->__construct('Saturday')
#1 {main}
  thrown in /Users/marianol/Code/stack-overflow/enums.php on line 8

Fatal error: Uncaught exception 'Exception' with message 'Not a week day.' in /Users/marianol/Code/stack-overflow/enums.php:8
Stack trace:
#0 /Users/marianol/Code/stack-overflow/enums.php(23): WeekDay->__construct('Saturday')
#1 {main}
  thrown in /Users/marianol/Code/stack-overflow/enums.php on line 8

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

person mlg    schedule 07.05.2016
comment
хорошее замечание о столбце базы данных. Я по-прежнему стою на своем, сколько строк используется в качестве аргументов функции при работе разработчиком программного обеспечения? Как много?? и это всегда очень четко определенный набор строк, который не позволяет делать все, что вы хотите. И нет способа выразить, что этот набор строк доступен. Очень жаль, что приходится обращаться к документам для каждой отдельной функции. - person Toskan; 09.05.2016
comment
@Toskan: И это хороший момент. Наличие компилятора (или интерпретатора), помогающего вам найти большинство проблем, — это именно то, что вы получаете со строго типизированными языками. - person mlg; 10.05.2016
comment
ну да, правда, но у статически типизированных языков тоже есть недостатки. Было бы неплохо, если бы в php корректно работала подсказка типов и были бы перечисления. Звучит так, будто вы много просите, но на самом деле это не так. Интересно, как работает подсказка типа python 3.x, поскольку с версии 3.4 у него есть перечисления. Отсутствие таких вещей — это просто программирование Микки Мауса. - person Toskan; 10.05.2016

Начиная с PHP 8.1 вы сможете использовать фактические перечисления.

enum A {
    case FOO = 'foo';
    case BAR = 'bar';
    case BAZ = 'baz';
}

Затем в вашей функции a() вы вводите подсказку для перечисления A.

function a(A $a) {
    echo $a->value;
}

Теперь a($a) будет принимать только:

a(A::FOO);
a(A::BAR);
a(A::BAZ);

или даже:

a(A::from('bar'));

но любой ввод, который не является допустимым case, завершится ошибкой с исключением ValueError.

person yivi    schedule 15.02.2021