为任何对象键入提示

我一直在研究打算用于对象的代码,而没有真正关心对象的types。 我想input提示,写的方法预期任何types的对象,但遇到了一些困难。

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

可捕获的致命错误:传递给MyClass :: MyFunc()的参数1必须是Object的一个实例,ObjectActualClass的实例给出

stdClass也是如此

我错过了什么? 我认为所有没有从另一个类inheritance的类都是从stdClassinheritance的,这意味着PHP中每个类的基类都是stdClass 。 不是这样吗?

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

实施这个的最好方法是创build一个名为Object的退化接口。 退化的接口意味着它没有定义的方法。

 interface Object { // leave blank } 

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

 class SomeBase implements Object { // your implementation } 

你现在可以调用你想要的function了

 function myFunc (Object $obj); myFunc($someBase); 

如果你传递了从你的Object接口inheritance的任何对象,这个types的提示将会通过。 如果你传入一个数组,int,string等,那么types提示将失败。

尽pipe对象没有types提示,但可以使用:

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

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

没有内置的机制来做到这一点,而不需要你的接口的所有用户扩展指定的类。 但是,为什么你要这样做呢? 所有的对象types有什么共同之处,足以使它们适合您的API的input?

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

如果你仍然想要类似于提示types的东西,最好的办法是用参数is_objectreplace运行时检查。

那么它只需要八年,但这将很快成为可能:PHP 7.2引入了objecttypes提示! 当我写这篇文章的时候,目前处于RFC阶段, 将于11月份发布 。

RFC:对象types提示

讨论

这个行为和你所期望的完全一样:

 <?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”

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

其中一个副作用就是object现在是一个保留字,不幸的是现在的@Gaz_Edge现有的解决scheme已经被破坏了。

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

打印出来:

你好,世界!
彼得
约翰

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

你可以做这样的事情:

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