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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/274360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 22:10:04  来源:igfitidea点击:

Checking if an instance's class implements an interface?

phpinterfaceoop

提问by Wilco

Given a class instance, is it possible to determine if it implements a particular interface? As far as I know, there isn't a built-in function to do this directly. What options do I have (if any)?

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

回答by

interface IInterface
{
}

class TheClass implements IInterface
{
}

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

You can use the "instanceof" operator. To use it, the left operand is a class instance and the right operand is an interface. It returns true if the object implements a particular interface.

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

回答by Jess Telford

As therefromherepoints out, you can use class_implements(). Just as with Reflection, this allows you to specify the class name as a string and doesn't require an instance of the class:

正如此处指出的那样,您可以使用class_implements(). 与反射一样,这允许您将类名指定为字符串,并且不需要类的实例:

interface IInterface
{
}

class TheClass implements IInterface
{
}

$interfaces = class_implements('TheClass');

if (isset($interfaces['IInterface'])) {
    echo "Yes!";
}

class_implements()is part of the SPL extension.

class_implements()是 SPL 扩展的一部分。

See: http://php.net/manual/en/function.class-implements.php

请参阅:http: //php.net/manual/en/function.class-implements.php

Performance Tests

性能测试

Some simple performance tests show the costs of each approach:

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

Given an instance of an object

给定一个对象的实例

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
'--------------------------------------------'

Given only a class name

只给出一个类名

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

Where the expensive __construct() is:

昂贵的 __construct() 在哪里:

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

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

These tests are based on this simple code.

这些测试基于这个简单的代码

回答by Bill Karwin

nlaq points out that instanceofcan be used to test if the object is an instance of a class that implements an interface.

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

But instanceofdoesn't distinguish between a class type and an interface. You don't know if the object is a classthat happens to be called IInterface.

instanceof不区分类类型和接口。你不知道,如果对象是一个恰好是叫IInterface

You can also use the reflection API in PHP to test this more specifically:

您还可以使用 PHP 中的反射 API 来更具体地测试:

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

See http://php.net/manual/en/book.reflection.php

http://php.net/manual/en/book.reflection.php

回答by d.raev

Just to help future searches is_subclass_ofis also a good variant (for PHP 5.3.7+):

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

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

回答by Starx

You can also do the following

您还可以执行以下操作

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

It will throw an recoverable error if the $objectSupposedToBeImplementingdoes not implement YourInterfaceInterface.

如果$objectSupposedToBeImplementing没有实现YourInterface接口,它将抛出一个可恢复的错误。

回答by Pilan

Update

更新

The is_afunctionis missing here as alternative.

此处缺少该is_a功能作为替代。

I did some performance tests to check which of the stated ways is the most performant.

我做了一些性能测试来检查哪种所述方式的性能最高。

Results over 100k iterations

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

Added some dots to actually "feel" see the difference.

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

Generated by this: https://3v4l.org/8Cog7

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

Conclusion

结论

In case you have an objectto check, use instance oflike mentioned in the accepted answer.

如果您有要检查的对象,请使用instance of已接受答案中提到的方法。

In case you have a classto check, use is_a.

如果您有要检查的课程,请使用is_a.

Bonus

奖金

Given the case you want to instantiate a class based on an interface you require it to have, it is more preformant to use is_a. There is only one exception - when the constructor is empty.

考虑到您想要基于您需要的接口实例化一个类的情况,使用is_a. 只有一种例外——构造函数为空时。

Example: is_a(<className>, <interfaceName>, true);

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

It will return bool. The third parameter "allow_string" allows it to check class names withoutinstantiating the class.

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