web-dev-qa-db-fra.com

Vérifier si la classe d'une instance implémente une interface?

Est-il possible de déterminer si une instance de classe implémente une interface particulière? Autant que je sache, il n'y a pas de fonction intégrée pour le faire directement. Quelles sont mes options (le cas échéant)?

139
Wilco
interface IInterface
{
}

class TheClass implements IInterface
{
}

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

Vous pouvez utiliser l'opérateur "instanceof". Pour l'utiliser, l'opérande gauche est une instance de classe et l'opérande droit est une interface. Il renvoie true si l'objet implémente une interface particulière.

240
user19302

Comme à partir de là indique, vous pouvez utiliser class_implements(). Comme avec Reflection, cela vous permet de spécifier le nom de la classe en tant que chaîne et ne nécessite pas d'instance de la classe:

interface IInterface
{
}

class TheClass implements IInterface
{
}

$interfaces = class_implements('TheClass');

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

class_implements() fait partie de l'extension SPL.

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

Des tests de performance

Quelques tests de performance simples montrent les coûts de chaque approche:

Étant donné une instance d'un objet

 Construction d'objet en dehors de la boucle (100 000 itérations) 
 ____________________________________________ 
 | class_implements | Réflexion | instanceOf | 
 | --------------- ------------ | ---------- - | 
 | 140 ms | 290 ms | 35 ms | 
 '--------------------------------------------- --- '
 
 Construction d'objet à l'intérieur de la boucle (100 000 itérations) 
 ____________________________________________ 
 | class_implements | Réflexion | instanceOf | 
 | ------------------ | ------------ | ---------- - | 
 | 182 ms | 340 ms | 83 ms | Constructeur pas cher 
 | 431 ms | 607 ms | 338 ms | Cher constructeur 
 '---------------------------------------------- - '

N'ayant qu'un nom de classe

 100 000 itérations 
 ____________________________________________ 
 | class_implements | Réflexion | instanceOf | 
 | ------------------ | ------------ | ---------- - | 
 | 149 ms | 295 ms | N/A | 
 '------------------------------------------------ ---- '

Où la coûteuse __construct () est:

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

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

Ces tests sont basés sur --- (ce code simple .

94
Jess Telford

nlaq souligne que instanceof peut être utilisé pour vérifier si l'objet est une instance d'une classe implémentant une interface.

Mais instanceof ne fait pas la distinction entre un type de classe et une interface. Vous ne savez pas si l'objet est une classe appelée IInterface.

Vous pouvez également utiliser l'API de réflexion dans PHP pour tester cela plus spécifiquement:

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

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

55
Bill Karwin

Juste pour aider les recherches futures is_subclass_of est aussi une bonne variante (pour PHP 5.3.7+):

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

Vous pouvez aussi faire ce qui suit

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

Il y aura une erreur récupérable si le $objectSupposedToBeImplementing n'implémente pas YourInterface interface.

5
Starx