php-任何obj的类型提示
我一直在研究旨在与对象一起使用的代码,而实际上并不关心对象的种类。 我想输入一些提示,即所编写的方法应使用任何类型的对象,但会遇到一些困难。
我尝试了stdClass和stdClass,但是当我尝试在以下对象中传递对象时,这两个都生成了错误:
可捕获的致命错误:传递给MyClass :: MyFunc()的参数1必须是object的实例,给定ObjectActualClass的实例
stdClass也发生了同样的情况
我想念什么? 我认为所有未显式继承自另一个类的类都继承自stdClass,这意味着PHP中每个类的基类都将是stdClass。不是这样吗?
GordonM asked 2020-02-16T10:06:51Z
9个解决方案
46 votes
stdClass不是基类! PHP类不会自动从任何类继承。 所有类都是独立的,除非它们显式扩展了另一个类。 在这方面,PHP与许多面向对象的语言不同。
Abdullah answered 2020-02-16T10:07:04Z
36 votes
实施此操作的最佳方法是创建一个名为Object的简并接口。简并接口意味着它没有定义的方法。
interface Object {
// leave blank
}
然后,在您的基类中,您可以实现Object。
class SomeBase implements Object {
// your implementation
}
现在,您可以根据需要调用函数
function myFunc (Object $obj);
myFunc($someBase);
如果传递任何从Object接口继承的对象,则此类型提示将通过。 如果您传入数组,整数,字符串等,则类型提示将失败。
Gaz_Edge answered 2020-02-16T10:07:38Z
11 votes
尽管没有对象的类型提示,但是您可以使用:
if (!is_object($arg)) {
return;
}
Ben answered 2020-02-16T10:07:58Z
11 votes
仅仅花了八年的时间,但这很快就会成为可能:PHP 7.2引入了object类型提示! 在我撰写本文时,它目前处于RFC阶段,定于11月发布。
11月30日更新:PHP 7.2已发布
RFC:对象类型提示
讨论区
这完全符合您的预期:
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)“酒吧”
致命错误:未被捕获的TypeError:传递给takeObject()的参数1必须是一个对象,给定字符串,在其中调用...
见[https://3v4l.org/Svuij]
副作用是object现在是保留字,不幸的是,这使@Gaz_Edge的现有解决方案无效。 幸运的是,您只需删除接口即可解决该问题。
iainn answered 2020-02-16T10:09:07Z
7 votes
没有所有对象都从其扩展的基类。 您只需删除typehint并在@param批注中记录所需的类型。
NikiC answered 2020-02-16T10:09:27Z
3 votes
没有要求您接口的所有用户扩展指定类的内置机制,都无法做到这一点。 但是您为什么仍要这样做呢? 所有对象类型的共同点是什么,足以使它们适合您的API?
即使能够像这样键入提示,您也一无所获。 另一方面,类型暗示参数以实现接口(例如is_object)将更有意义。
如果您仍希望输入提示,则最好的方法是将运行时检查替换为参数is_object。
Jon answered 2020-02-16T10:09:57Z
2 votes
从php 7.2开始,此功能现已实现。 您现在可以为任何对象键入提示。
function myFunc(Object $myObject) : Object {
return $myObject;
}
您可以在官方文档中查看
Ophidian answered 2020-02-16T10:10:21Z
1 votes
适用于test.php的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);
打印输出:
你好,世界!
彼得
约翰
可捕获的致命错误:传递给Test :: hello()的参数1必须是stdClass的实例,给定的整数,在第32行的test.php中调用并在第5行的test.php中定义
lubosdz answered 2020-02-16T10:11:07Z
-3 votes
您可以执行以下操作:
function myFunc ($obj)
{
if ($obj instanceof stdClass) { .... }
}
Alon Eitan answered 2020-02-16T10:11:28Z