为任何对象键入提示

时间:2011-10-20 16:21:51

标签: php type-hinting

我一直致力于打算与对象一起使用的代码,而不是真正关心对象的类型。我想输入提示,正在编写的方法需要任何类型的对象,但遇到了一些困难。

我尝试了function myFunc (object $obj)function myFunc (stdClass $obj),但当我尝试传递对象时,这两个都会产生错误:

  

捕获致命错误:传递给MyClass :: MyFunc()的参数1必须是对象的实例,给定的ObjectActualClass实例

stdClass以及

也是如此

我错过了什么?我认为所有未明确继承自另一个类的类都继承自stdClass,这意味着PHP中每个类的基类都是stdClass。情况不是这样吗?

9 个答案:

答案 0 :(得分:45)

stdClass不是基类! PHP类不会自动从任何类继承。所有类都是独立的,除非它们显式扩展另一个类。 PHP在这方面与许多面向对象的语言不同。

答案 1 :(得分:36)

强制执行此操作的最佳方法是创建名为Object的简并接口。简并接口意味着它没有定义的方法。

interface Object {

   // leave blank

}

然后在您的基类中,您可以实现Object

class SomeBase implements Object {

   // your implementation

}

您现在可以根据需要调用您的功能

function myFunc (Object $obj);

myFunc($someBase);

如果传递任何继承自Object接口的对象,则此类型提示将通过。如果传入数组,int,string等,则类型提示将失败。

答案 2 :(得分:11)

虽然对象没有类型提示,但您可以使用:

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

答案 3 :(得分:11)

好吧只用了8年,但很快就可以实现:PHP 7.2引入了object类型提示! 在我写这篇文章时,它目前处于RFC阶段,is due to be released in November

更新,11月30日: PHP 7.2 has been released

RFC: Object typehint

Discussion

这与您的预期完全相同:

<?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)&#34; Foo&#34;

     

string(3)&#34; Bar&#34;

     

致命错误:未捕获的TypeError:传递给takeObject()的参数1必须是一个对象,给定的字符串,在...中调用...

请参阅https://3v4l.org/Svuij

这样做的另一个副作用是object is now a reserved word,不幸的是,它会在broken之上呈现@ Gaz_Edge的现有解决方案。幸运的是,你需要做的就是删除界面。

答案 4 :(得分:7)

没有所有对象扩展的基类。您应该只删除typehint并在@param注释中记录预期的类型。

答案 5 :(得分:3)

没有内置机制可以在不要求接口的所有用户扩展指定类的情况下执行此操作。但是你为什么要这样做呢?所有对象类型的共同点是什么,足以使它们成为API的合适输入?

即使能够输入这样的提示,你很可能也无法获得任何东西。另一方面,键入提示参数来实现接口(例如Traversable)会更有意义。

如果您仍然需要类似于提示类型的内容,那么您可以做的最好的事情就是在参数上用is_object替换运行时检查。

答案 6 :(得分:2)

从PHP 7.2开始,此功能现已实施。你现在可以输入任何对象的提示。

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

您可以在official documentation

中查看此内容

答案 7 :(得分:1)

stdClass的Typehint自PHP 5.3+起作用(如果我没错)。 以下是使用stdClass构造的typehint的有效代码:

示例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!
  彼得
  约翰

     

可捕获的致命错误:传递给Test :: hello()的参数1必须是stdClass的实例,给定整数,在第32行的test.php中调用,在第5行的test.php中定义

答案 8 :(得分:-3)

你可以这样做:

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