ChatGPT解决这个技术问题 Extra ChatGPT

任何对象的类型提示

I've been working on code that's intended to be used with objects, without really caring what the kind of object is. I wanted to type hint that the method being written expected an object of any type, but ran into some difficulty.

I tried function myFunc (object $obj) and function myFunc (stdClass $obj) but both of these generated errors when I tried to pass objects in:

Catchable fatal error: Argument 1 passed to MyClass::MyFunc() must be an instance of object, instance of ObjectActualClass given

The same happened with stdClass as well

What am I missing? I thought that all classes that didn't explicitly inherit from another class inherited from stdClass, meaning that the base class of every class in PHP would be stdClass. Is this not the case?

see my answer for the complete solution

A
Abdullah

stdClass is NOT a base class! PHP classes do not automatically inherit from any class. All classes are standalone, unless they explicitly extend another class. PHP differs from many object-oriented languages in this respect.


this is correct, but for a complete solution to this problem, see my answer below. I show you how you can type hint for an object stackoverflow.com/questions/7839059/type-hinting-for-any-object/…
this is now possible since PHP 7.2. see @iainn's answer below: stackoverflow.com/a/46444235/3179423
G
GWed

The best way to enforce this would be to create a degenerate interface called Object. A degenerate interface means it has no defined methods.

interface Object {

   // leave blank

}

Then in your base classes, you can implement Object.

class SomeBase implements Object {

   // your implementation

}

You can now call your function as you wanted to

function myFunc (Object $obj);

myFunc($someBase);

If you pass any object which inherits from your Object interface, this type hint will pass. If you pass in an array, int, string etc, the type hint will fail.


+1 because this is the best oop answer.. you should always type hint on interfaces only
If your class structure is more hierarchical, couldn't you just extends stdClass in the base classes?
OP is already using stdClass but it doesnt work because stdClass is not the base for all objects; not like java or so.
I agree with your comment above, but i don't agree with the solution. Cause in your case, you suppose everything defined by yourself, but in our modern life, we all use frameworks, and then they are already defined. So it seems no good solution to do a type hint on objects
C
Community

Well it only took eight years, but this will soon be possible: PHP 7.2 introduces the object type hint! As I write this, it's currently in the RFC stage, and is due to be released in November.

Update, 30th November: PHP 7.2 has been released

RFC: Object typehint

Discussion

This behaves exactly as you might expect:

<?php

class Foo {}
class Bar {}

function takeObject(object $obj) {
    var_dump(get_class($obj));
}

takeObject(new Foo);
takeObject(new Bar);
takeObject('not an object');

Will result in:

string(3) "Foo" string(3) "Bar" Fatal error: Uncaught TypeError: Argument 1 passed to takeObject() must be an object, string given, called in...

See https://3v4l.org/Svuij

One side-effect of this is that object is now a reserved word, which unfortunately renders @Gaz_Edge's existing solution above broken. Fortunately, all you have to do to fix it is delete the interface.


B
Ben

Although there is no type hinting for objects, you can use:

if (!is_object($arg)) {
    return;
}

N
NikiC

There is no base class that all objects extend from. You should just remove the typehint and document the expected type in the @param annotation.


J
Jon

There is no built-in mechanism to do this without requiring all users of your interface to extend a specified class. But why would you want to do this anyway? What do all object types have in common that's enough to make them suitable input for your API?

In all probability you wouldn't gain anything even if able to type hint like this. On the other hand, type hinting a parameter to implement an interface (such as Traversable) would be much more meaningful.

If you still want something akin to type hinting, the best you can do is substitute a runtime check with is_object on the parameter.


D
DisgruntledGoat

As of php 7.2 this feature has now been implemented. you can type hint for any object now.

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

You can review this in the official documentation


7
7ochem

Typehint for stdClass works since PHP 5.3+ (if I am not wrong). Following is valid code using typehint for stdClass construct:

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

Prints out:

Hello world! Peter John Catchable fatal error: Argument 1 passed to Test::hello() must be an instance of stdClass, integer given, called in test.php on line 32 and defined in test.php on line 5


A
Alon Eitan

You could do something like this:

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

Not all Objects are derived from stdClass. And this is equivalent to including stdClass as the type hint for $obj