Подсказка типа PHP для разрешения Array или ArrayAccess

Можно ли разрешить массив или объект, который реализует ArrayAccess?

Например:

class Config implements ArrayAccess {
    ...
}

class I_Use_A_Config
{
    public function __construct(Array $test)
    ...
}

Я хочу быть в состоянии передать либо Array или ArrayAccess.

Есть ли чистый способ сделать это, кроме проверки типа параметра вручную?

4 ответа

Решение

Нет, нет "чистого" способа сделать это.

array тип является примитивным типом. Объекты, которые реализуют ArrayAccess Интерфейс основан на классах, также известных как составной тип. Нет подсказки типа, которая охватывает оба.

Поскольку вы используете ArrayAccess как массив вы можете просто привести его. Например:

$config = new Config;
$lol = new I_Use_A_Config( (array) $config);

Если это не вариант (вы хотите использовать Config объект как он есть) затем просто удалите подсказку типа и убедитесь, что это либо массив, либо ArrayAccess, Я знаю, что вы хотели избежать этого, но это не имеет большого значения. Это всего лишь несколько строк и, когда все сказано и сделано, несущественно.

PHP 8.0+

Вы можете использовать объединение array и ArrayAccess.

      class I_Use_A_Config
{
    public function __construct(array|ArrayAccess $test)
    ...
}

У них есть реальное решение в PHP 7.1.

http://php.net/manual/en/migration71.new-features.php

Итеративный псевдотип - это то, что вы хотите. Любой массив или тип Traversable (который является базовым интерфейсом для итераторов) пройдет эту проверку.

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

http://php.net/manual/en/function.iterator-to-array.php

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

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

Ну и php поддерживает подсказки типа для Array/Object. Таким образом, массив должен работать нормально. Однако передача объекта ArrayAccess по методу, разрешенному только для типа Array, может вызвать ошибки. ArrayAccess используется главным образом с целью итерации объекта ArrayAccess таким же образом, как массив, как при использовании в foreach.

Другие вопросы по тегам