Тип подсказки для любого объекта

Я работал над кодом, который предназначен для использования с объектами, не заботясь о том, что такое объект. Я хотел ввести подсказку о том, что написанный метод ожидает объект любого типа, но натолкнулся на некоторые трудности.

Я попробовал function myFunc (object $obj) и function myFunc (stdClass $obj) но обе эти сгенерированные ошибки, когда я пытался передать объекты в:

Допустимая фатальная ошибка: аргумент 1, переданный MyClass :: MyFunc () должен быть экземпляром объекта, экземпляр объекта ObjectActualClass

То же самое произошло и с stdClass

Что мне не хватает? Я думал, что все классы, которые явно не наследуются от другого класса, унаследованного от stdClass , что означает, что базовый класс каждого класса в PHP будет stdClass . Разве это не так?

Related of "Тип подсказки для любого объекта"

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) { .... } }