Реализовать интерфейс PHP таким образом, чтобы экземпляр объекта мог передаваться как аргумент типа массива? - PullRequest
2 голосов
/ 03 июня 2009

В PHP можно указывать типы аргументов, хотя они называют это хинтингом типов.

Я реализую интерфейс, в котором одна из функций указывает массив в качестве типа аргумента:

function myFunction(array $argument){
}

Я бы хотел определить класс, экземпляр которого можно использовать в качестве аргумента для этой функции. Другими словами это расширило бы ArrayObject или реализовало бы ArrayAccess или что-то в этом роде.

Есть ли встроенный интерфейс или абстрактный класс, который будет работать для этого? (ArrayObject не делает)

Ответы [ 3 ]

3 голосов
/ 03 июня 2009

Это невозможно. array() не является объектом какого-либо класса. Следовательно, он не может реализовать какие-либо интерфейс (см. здесь ). Таким образом, вы не можете использовать объект и массив взаимозаменяемо. Решение сильно зависит от того, чего вы хотите достичь.

Почему бы вам не изменить сигнатуру функции, чтобы разрешить только ArrayObject с, ArrayIterator с, ArrayAccess с, IteratorAggregate с, Iterator с или Traversable с (в зависимости от того, что вы ' хотел бы сделать внутри функции)?

Если вам приходится полагаться на возможности взаимодействия переданного объекта, вы должны использовать Traversable в качестве подсказки типа. Это обеспечит возможность использования объекта с foreach(). Если вам нужен доступ к объекту в виде массива (например, $test['test']), вы должны использовать ArrayAccess в качестве подсказки типа. Но если вам нужно, чтобы переданный объект имел определенный пользовательский тип, используйте пользовательский тип в качестве подсказки типа.

Другой вариант - вообще не использовать подсказку типа и определять тип передаваемого аргумента в теле функции и обрабатывать аргумент соответствующим образом (или генерировать InvalidArgumentException или что-то в этом роде).

if (is_array($arg)) { ... }
else if ($arg instanceof Traversable) { ... }
else if ($arg instanceof ArrayAccess) { ... }
else {
    throw new InvalidArgumentException('...');
}
2 голосов
/ 03 июня 2009

Нет, но я бы предложил две альтернативы:

  1. Удалите массив , спецификатор и, скорее, проверьте внутри функции, используя is_array и instanceof ArrayObject
  2. Используйте (массив) $ ArrayObject при вызове подпрограммы или как часть 1. выше.

Пример для soulmerge : -)

function myFunction(array $argument){
    echo var_export($argument,true);
}
$a = new ArrayObject();
$a[] = 'hello';
$a[] = 'and goodbye';

myFunction((array)$a);  

выходы * * 1016

 array (
   0 => 'hello',
   1 => 'and goodbye',
 )
0 голосов
/ 03 июня 2009

Нет, это невозможно, так как массив является примитивным типом в PHP. Экземпляр класса - это объект, и на этом этапе внутреннее сравнение PHP уже останавливается (интерфейсы и т.п. не проверяются).

Вы можете создать массив из вашего объекта:

$array = array();
foreach ($yourObject as $key => $value) {
    $array[$key] = $value;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...