Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 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) { .... }
}