PHP Тип намека, чтобы разрешить Array или ArrayAccess

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

Например:

class Config implements ArrayAccess {
    ...
}

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

Я хочу иметь возможность передать либо Array, либо ArrayAccess.

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

Ответ 1

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

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

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

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

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

Ответ 2

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

http://php.net/manual/en/migration71.new-features.php#migration71.new-features.iterable-pseudo-type

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

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

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

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

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

Ответ 3

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