Тип подсказки для любого объекта
Я работаю над кодом, который предназначен для использования с объектами, не заботясь о том, что такое объект. Я хотел ввести подсказку о том, что написанный метод ожидает объект любого типа, но натолкнулся на некоторые трудности.
Я пробовал function myFunc (object $obj)
и function myFunc (stdClass $obj)
, но обе эти сгенерированные ошибки, когда я пытался передать объекты в:
Допустимая фатальная ошибка: аргумент 1, переданный MyClass:: MyFunc() должен быть экземпляром объекта, экземпляр ObjectActualClass, указанный
То же самое произошло и с stdClass
Что мне не хватает? Я думал, что все классы, которые явно не наследуются от другого класса, унаследованного от stdClass
, что означает, что базовый класс каждого класса в PHP будет stdClass
. Это не так?
Ответы
Ответ 1
stdClass НЕ является базовым классом! Классы PHP автоматически не наследуются от какого-либо класса. Все классы являются автономными, если только они явно не расширяют другой класс. PHP отличается от многих объектно-ориентированных языков в этом отношении.
Ответ 2
Лучшим способом обеспечения этого будет создание вырожденного интерфейса с именем Object
. Вырожденный интерфейс означает, что он не имеет определенных методов.
interface Object {
// leave blank
}
Затем в ваших базовых классах вы можете реализовать Object
.
class SomeBase implements Object {
// your implementation
}
Теперь вы можете вызывать свою функцию так, как вы хотели
function myFunc (Object $obj);
myFunc($someBase);
Если вы передадите любой объект, который наследуется от вашего интерфейса Object
, этот тип подсказки пройдет. Если вы передадите массив, int, строку и т.д., Подсказка типа не будет выполнена.
Ответ 3
Хотя для объектов нет намека на тип, вы можете использовать:
if (!is_object($arg)) {
return;
}
Ответ 4
Нет базового класса, из которого все объекты распространяются. Вы должны просто удалить typehint и документировать ожидаемый тип в аннотации @param
.
Ответ 5
Для этого не существует встроенного механизма, не требующего от всех пользователей вашего интерфейса расширения указанного класса. Но почему вы все равно хотите это сделать? Что общего у всех типов объектов, что достаточно, чтобы сделать их подходящими для вашего API?
По всей вероятности, вы не получите ничего, даже если сможете набирать подсказку вроде этого. С другой стороны, тип подсказки для реализации интерфейса (например, Traversable
) будет гораздо более значимым.
Если вы все еще хотите что-то вроде намека на тип, лучшее, что вы можете сделать, это заменить проверку выполнения с помощью is_object
на параметре.
Ответ 6
Ну, это заняло всего восемь лет, но это скоро будет возможно: PHP 7.2 вводит подсказку типа object
! Как я пишу это, он в настоящее время находится на стадии RFC, и должен быть выпущен в ноябре.
Обновление, 30 ноября: Опубликован PHP 7.2
RFC: Object typehint
Обсуждение
Это ведет себя точно так, как вы могли ожидать:
<?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) "Бар"
Fatal error: Uncaught TypeError: аргумент 1, переданный в takeObject(), должен быть объектом, указанным строкой, вызываемым в...
Одним из побочных эффектов этого является то, что object
теперь является зарезервированным словом, что, к сожалению, делает существующее решение @Gaz_Edge выше сломанным.
Ответ 7
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
Ответ 8
Как и в php 7.2, эта функция теперь реализована. вы можете ввести подсказку для любого объекта сейчас.
function myFunc(Object $myObject) : Object {
return $myObject;
}
Вы можете просмотреть это в официальной документации
Ответ 9
Вы можете сделать что-то вроде этого:
function myFunc ($obj)
{
if ($obj instanceof stdClass) { .... }
}