Тип подсказки для любого объекта - PullRequest
46 голосов
/ 20 октября 2011

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

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

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

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

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

Ответы [ 9 ]

45 голосов
/ 20 октября 2011

stdClass НЕ является базовым классом! Классы PHP не наследуются автоматически ни от одного класса. Все классы автономны, если они явно не расширяют другой класс. В этом отношении PHP отличается от многих объектно-ориентированных языков.

36 голосов
/ 28 апреля 2014

Лучший способ обеспечить это - создать вырожденный интерфейс с именем Object.Вырожденный интерфейс означает, что у него нет определенных методов.

interface Object {

   // leave blank

}

Тогда в ваших базовых классах вы можете реализовать Object.

class SomeBase implements Object {

   // your implementation

}

Теперь вы можете вызывать свою функцию так, как вам хочетсяto

function myFunc (Object $obj);

myFunc($someBase);

Если вы передадите какой-либо объект, который унаследован от вашего интерфейса Object, подсказка этого типа пройдет.Если вы передадите массив, int, string и т. Д., Подсказка типа потерпит неудачу.

12 голосов
/ 27 сентября 2017

Ну, прошло всего восемь лет, но это скоро станет возможным: 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');

В результате:

string (3) "Foo"

string (3) "Bar"

Неустранимая ошибка: Uncaught TypeError: Аргумент 1, переданный в takeObject (), должен быть объектом, заданной строкой, вызванной в ...

См. https://3v4l.org/Svuij

Одна сторонаВ результате object теперь является зарезервированным словом , что, к сожалению, делает существующее решение @ Gaz_Edge выше нарушено .К счастью, все, что вам нужно сделать - это удалить интерфейс.

11 голосов
/ 11 октября 2013

Хотя для объектов нет хинтинга, вы можете использовать:

if (!is_object($arg)) {
    return;
}
7 голосов
/ 20 октября 2011

Нет базового класса, из которого распространяются все объекты. Вам следует просто удалить указание и указать ожидаемый тип в аннотации @param.

3 голосов
/ 20 октября 2011

Нет встроенного механизма для этого, не требующего от всех пользователей вашего интерфейса расширения указанного класса.Но зачем тебе это делать?Что общего у всех типов объектов, этого достаточно для того, чтобы сделать их подходящим входом для вашего API?

По всей вероятности, вы ничего не получите, даже если сможете напечатать подсказку, подобную этой.С другой стороны, тип подсказки для параметра для реализации интерфейса (такой как Traversable) будет гораздо более значимым.

Если вы все еще хотите что-то похожее на подсказку типа, лучшее, что вы можете сделать, это заменитьпроверка во время выполнения с параметром is_object.

2 голосов
/ 19 декабря 2017

Начиная с версии 7.2 эта функция была реализована.Вы можете напечатать подсказку для любого объекта сейчас.

function myFunc(Object $myObject) : Object {
    return $myObject;
}

Вы можете просмотреть это в официальной документации

1 голос
/ 24 ноября 2012

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);

Печать:

Hello world!
Peter
John

Исправляемая фатальная ошибка: аргумент 1, передаваемый в Test :: hello (), должен быть экземпляром stdClass, заданным целым числом, вызываемым в test.php в строке 32 и определенным в test.php встрока 5

0 голосов
/ 20 октября 2011

Вы можете сделать что-то вроде этого:

function myFunc ($obj)
{
     if ($obj instanceof stdClass) { .... }
}
...