Checking if an instance's class implements an interface?

前端 未结 6 1166
误落风尘
误落风尘 2020-12-12 21:09

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 opt

相关标签:
6条回答
  • 2020-12-12 21:52

    Update

    The is_a function is missing here as alternative.

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

    Results over 100k iterations

          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

    Conclusion

    In case you have an object to check, use instance of like mentioned in the accepted answer.

    In case you have a class to check, use 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.

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

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

    0 讨论(0)
  • 2020-12-12 21:56

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

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

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

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

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

    0 讨论(0)
  • 2020-12-12 21:58

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

    if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
        echo 'I can do it!';
    }
    
    0 讨论(0)
  • 2020-12-12 22:04

    You can also do the following

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

    It will throw an recoverable error if the $objectSupposedToBeImplementing does not implement YourInterface Interface.

    0 讨论(0)
  • 2020-12-12 22:05
    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.

    0 讨论(0)
  • 2020-12-12 22:05

    As therefromhere points 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:

    interface IInterface
    {
    }
    
    class TheClass implements IInterface
    {
    }
    
    $interfaces = class_implements('TheClass');
    
    if (isset($interfaces['IInterface'])) {
        echo "Yes!";
    }
    

    class_implements() is part of the SPL extension.

    See: 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:

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

    These tests are based on this simple code.

    0 讨论(0)
提交回复
热议问题