给定一个类实例,是否可以确定它是否实现了特定的接口?据我所知,没有直接执行此操作的内置函数。我有哪些选项(如果有)?
给定一个类的实例,如何判断其是否实现了某个特定的接口呢?据我所知,没有直接的内置函数可以完成这个任务。那么我有哪些选项呢?interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
正如therefromhere所指出的那样,您可以使用class_implements()
。就像反射一样,这允许您将类名指定为字符串,而不需要类的实例:
interface IInterface
{
}
class TheClass implements IInterface
{
}
$interfaces = class_implements('TheClass');
if (isset($interfaces['IInterface'])) {
echo "Yes!";
}
class_implements()
是SPL扩展的一部分。
参见:http://php.net/manual/en/function.class-implements.php
一些简单的性能测试显示了每种方法的成本:
在循环外构建对象(100,000次迭代) ____________________________________________ | class_implements | Reflection | instanceOf | |------------------|------------|------------| | 140毫秒 | 290毫秒 | 35毫秒 | '--------------------------------------------'
在循环内构建对象(100,000次迭代) ____________________________________________ | class_implements | Reflection | instanceOf | |------------------|------------|------------| | 182毫秒 | 340毫秒 | 83毫秒 | Cheap Constructor | 431毫秒 | 607毫秒 | 338毫秒 | Expensive Constructor '--------------------------------------------'
100,000次迭代 ____________________________________________ | class_implements | Reflection | instanceOf | |------------------|------------|------------| | 149毫秒 | 295毫秒 | N/A | '--------------------------------------------'
其中贵重的__construct()位于:
public function __construct() {
$tmp = array(
'foo' => 'bar',
'this' => 'that'
);
$in = in_array('those', $tmp);
}
这些测试基于这个简单代码。
nlaq指出,instanceof
可用于测试对象是否是实现接口的类的实例。
但是instanceof
不能区分类类型和接口。您不知道对象是否是被称为IInterface
的类。
您还可以在PHP中使用反射API进行更具体的测试:
$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
print "Yep!\n";
}
instanceof
。 - flu这里缺少is_a
函数作为替代方案。
我进行了一些性能测试,以确定哪种方法是最高效的。
instanceof [object] took 7.67 ms | + 0% | ..........
is_a [object] took 12.30 ms | + 60% | ................
is_a [class] took 17.43 ms | +127% | ......................
class_implements [object] took 28.37 ms | +270% | ....................................
reflection [class] took 34.17 ms | +346% | ............................................
添加了一些点以实际"感受"并看到区别。
如果你有一个要检查的对象,请像接受的答案中提到的那样使用instanceof
。
如果你有一个要检查的类,请使用is_a
。
假设你想根据所需接口实例化一个类,使用is_a
更加高效。只有一个例外-当构造函数为空时。
示例:
is_a(<className>, <interfaceName>, true);
它将返回bool
。第三个参数“allow_string”允许其在不实例化类的情况下检查类名。
is_subclass_of
添加到脚本中。https://3v4l.org/FY4re - Dan Masonif (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
echo 'I can do it!';
}
public function yourMethod(YourInterface $objectSupposedToBeImplementing) {
//.....
}
如果$objectSupposedToBeImplementing
没有实现YourInterface
接口,它会抛出可恢复的错误。