Я работал над кодом, который предназначен для использования с объектами, не заботясь о том, что такое объект. Я хотел ввести подсказку о том, что написанный метод ожидает объект любого типа, но натолкнулся на некоторые трудности.
Я попробовал function myFunc (object $obj)
и function myFunc (stdClass $obj)
но обе эти сгенерированные ошибки, когда я пытался передать объекты в:
Допустимая фатальная ошибка: аргумент 1, переданный MyClass :: MyFunc () должен быть экземпляром объекта, экземпляр объекта ObjectActualClass
То же самое произошло и с stdClass
Что мне не хватает? Я думал, что все классы, которые явно не наследуются от другого класса, унаследованного от stdClass
, что означает, что базовый класс каждого класса в PHP будет stdClass
. Разве это не так?
stdClass НЕ является базовым классом! Классы PHP автоматически не наследуются от какого-либо класса. Все классы являются автономными, если только они явно не расширяют другой класс. В этом отношении PHP отличается от многих объектно-ориентированных языков.
Лучший способ обеспечить это – создать вырожденный интерфейс под названием Object
. Вырожденный интерфейс означает, что он не имеет определенных методов.
interface Object { // leave blank }
Затем в базовых классах вы можете реализовать Object
.
class SomeBase implements Object { // your implementation }
Теперь вы можете вызывать свою функцию так, как вы хотели
function myFunc (Object $obj); myFunc($someBase);
Если вы передадите любой объект, который наследуется от вашего интерфейса Object
, этот тип подсказки пройдет. Если вы передадите массив, int, строку и т. Д., Подсказка типа не будет выполнена.
Хотя для объектов нет намека на тип, вы можете использовать:
if (!is_object($arg)) { return; }
Нет базового класса, из которого все объекты распространяются. Вы должны просто удалить typehint и документировать ожидаемый тип в аннотации @param
.
Для этого не существует встроенного механизма, не требуя от всех пользователей вашего интерфейса расширения указанного класса. Но почему вы все равно хотите это сделать? Что общего у всех типов объектов, что достаточно, чтобы сделать их подходящими для вашего API?
По всей вероятности, вы не получите ничего, даже если сможете набирать намек вроде этого. С другой стороны, тип намека на параметр для реализации интерфейса (например, Traversable
) будет гораздо более значимым.
Если вы все еще хотите что-то похожее на тип намека, лучше всего вы можете заменить проверку выполнения с помощью is_object
на параметр.
Ну, прошло всего восемь лет, но это скоро будет возможно: PHP 7.2 вводит подсказку типа object
! Когда я пишу это, он в настоящее время находится на стадии RFC и должен быть выпущен в ноябре .
Обновление, 30 ноября: выпущен PHP 7.2
RFC: Тип объекта
обсуждение
Это ведет себя точно так, как вы могли ожидать:
<?php class Foo {} class Bar {} function takeObject(object $obj) { var_dump(get_class($obj)); } takeObject(new Foo); takeObject(new Bar); takeObject('not an object');
Это приведет к:
строка (3) "Foo"
строка (3) "Бар"
Неустранимая ошибка: Uncaught TypeError: Аргумент 1, переданный в takeObject (), должен быть объектом, заданной строкой, вызываемой …
Одним из побочных эффектов этого является то, что object
теперь является зарезервированным словом, что, к сожалению, делает существующее решение @Gaz_Edge выше сломанным.
Typehint для stdClass
работает с PHP 5.3+ (если я не ошибаюсь). Ниже приведен допустимый код с использованием typehint для конструкции stdClass
:
Пример test.php
:
class Test{ function hello(stdClass $o){ echo $o->name; } } class Arg2 extends stdClass{ public $name = 'John'; function sayHello(){ echo 'Hello world!'; } } $Arg1 = new stdClass(); $Arg1->name = 'Peter'; $Arg2 = new Arg2(); $Arg2->sayHello(); $test = new Test(); // OK $test->hello($Arg1); $test->hello($Arg2); // fails $test->hello(1);
Распечатывает:
Привет мир!
Питер
ДжонДопустимая фатальная ошибка: аргумент 1, переданный в Test :: hello (), должен быть экземпляром stdClass, целочисленным, указанным в test.php в строке 32 и определенным в test.php в строке 5
Начиная с php 7.2 эта функция реализована. вы можете ввести подсказку для любого объекта сейчас.
function myFunc(Object $myObject) : Object { return $myObject; }
Вы можете просмотреть это в официальной документации
Вы могли бы сделать что-то вроде этого:
function myFunc ($obj) { if ($obj instanceof stdClass) { .... } }