为任何对象键入提示
我一直在研究打算用于对象的代码,而没有真正关心对象的types。 我想input提示,写的方法预期任何types的对象,但遇到了一些困难。
我尝试function myFunc (object $obj)
和function myFunc (stdClass $obj)
但是当我试图传递对象时,这两个产生的错误:
可捕获的致命错误:传递给MyClass :: MyFunc()的参数1必须是Object的一个实例,ObjectActualClass的实例给出
stdClass
也是如此
我错过了什么? 我认为所有没有从另一个类inheritance的类都是从stdClass
inheritance的,这意味着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_object
replace运行时检查。
那么它只需要八年,但这将很快成为可能:PHP 7.2引入了object
types提示! 当我写这篇文章的时候,目前处于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) { .... } }