检查实例的类是否实现了接口?

时间:2008-11-08 04:24:28

标签: php interface oop

给定一个类实例,是否可以确定它是否实现了特定的接口?据我所知,没有内置函数可以直接执行此操作。我有什么选择(如果有的话)?

6 个答案:

答案 0 :(得分:234)

interface IInterface
{
}

class TheClass implements IInterface
{
}

$cls = new TheClass();
if ($cls instanceof IInterface) {
    echo "yes";
}

您可以使用“instanceof”运算符。要使用它,左操作数是一个类实例,右操作数是一个接口。如果对象实现特定接口,则返回true。

答案 1 :(得分:89)

therefromhere所述,您可以使用class_implements()。与Reflection一样,这允许您将类名指定为字符串,并且不需要该类的实例:

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

性能测试

一些简单的性能测试显示了每种方法的成本:

给定一个对象的实例

Object construction outside the loop (100,000 iterations)
 ____________________________________________
| class_implements | Reflection | instanceOf |
|------------------|------------|------------|
| 140 ms           | 290 ms     | 35 ms      |
'--------------------------------------------'

Object construction inside the loop (100,000 iterations)
 ____________________________________________
| class_implements | Reflection | instanceOf |
|------------------|------------|------------|
| 182 ms           | 340 ms     | 83 ms      | Cheap Constructor
| 431 ms           | 607 ms     | 338 ms     | Expensive Constructor
'--------------------------------------------'

仅提供班级名称

100,000 iterations
 ____________________________________________
| class_implements | Reflection | instanceOf |
|------------------|------------|------------|
| 149 ms           | 295 ms     | N/A        |
'--------------------------------------------'

昂贵的__construct()在哪里:

public function __construct() {
    $tmp = array(
        'foo' => 'bar',
        'this' => 'that'
    );  

    $in = in_array('those', $tmp);
}

这些测试基于this simple code

答案 2 :(得分:55)

nlaq指出instanceof可用于测试对象是否是实现接口的类的实例。

但是instanceof不区分类类型和接口。您不知道该对象是否恰好被称为IInterface

您还可以使用PHP中的反射API对此进行更具体的测试:

$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
  print "Yep!\n";
}

请参阅http://php.net/manual/en/book.reflection.php

答案 3 :(得分:17)

只是为了帮助将来的搜索is_subclass_of也是一个很好的变体(对于PHP 5.3.7 +):

if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
    echo 'I can do it!';
}

答案 4 :(得分:5)

您还可以执行以下操作

public function yourMethod(YourInterface $objectSupposedToBeImplementing) {
   //.....
}

如果$objectSupposedToBeImplementing未实现YourInterface接口,则会抛出可恢复的错误。

答案 5 :(得分:4)

更新

这里缺少is_a function

我做了一些性能测试,以检查哪种陈述的方式是最有效的。

结果超过10万次迭代

      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% | ............................................

添加了一些点以实际“感觉到”差异。

由此生成:https://3v4l.org/8Cog7

结论

如果要检查对象,请使用instance of,如接受的答案中所述。

如果要检查 class ,请使用is_a

奖金

鉴于您要基于所需的接口实例化一个类的情况,使用is_a更为方便。只有一个例外-构造函数为空。

示例: is_a(<className>, <interfaceName>, true);

它将返回bool。第三个参数“ allow_string”允许它在不实例化类的情况下检查类名。