Prüfen, ob die Klasse einer Instanz eine Schnittstelle implementiert?

Lesezeit: 4 Minuten

Ist es bei einer gegebenen Klasseninstanz möglich festzustellen, ob sie eine bestimmte Schnittstelle implementiert? Soweit ich weiß, gibt es keine eingebaute Funktion, um dies direkt zu tun. Welche Möglichkeiten habe ich (falls vorhanden)?

interface IInterface
{
}

class TheClass implements IInterface
{
}

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

Sie können den „instanceof“-Operator verwenden. Um es zu verwenden, ist der linke Operand eine Klasseninstanz und der rechte Operand eine Schnittstelle. Es gibt true zurück, wenn das Objekt eine bestimmte Schnittstelle implementiert.

  • Beachten Sie, dass dies nicht nützlich ist, wenn Sie versuchen, den Konstruktor der Klasse zu bestimmen

    – AaA

    23. November 2020 um 8:12 Uhr

Benutzer-Avatar
Jess Telford

Wie daraus hervorgeht, können Sie verwenden class_implements(). Genau wie bei Reflection können Sie damit den Klassennamen als Zeichenfolge angeben und benötigen keine Instanz der Klasse:

interface IInterface
{
}

class TheClass implements IInterface
{
}

$interfaces = class_implements('TheClass');

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

class_implements() ist Teil der SPL-Erweiterung.

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

Leistungstests

Einige einfache Leistungstests zeigen die Kosten jedes Ansatzes:

Gegeben eine Instanz eines Objekts

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

Gegeben ist nur ein Klassenname

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

Wo das teure __construct() ist:

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

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

Diese Tests basieren auf dieser einfache Code.

Benutzer-Avatar
Bill Karwin

nlaq weist darauf hin instanceof kann verwendet werden, um zu testen, ob das Objekt eine Instanz einer Klasse ist, die eine Schnittstelle implementiert.

Aber instanceof unterscheidet nicht zwischen einem Klassentyp und einer Schnittstelle. Sie wissen nicht, ob das Objekt a ist Klasse das heißt zufällig IInterface.

Sie können dies auch mit der Reflection-API in PHP genauer testen:

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

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

  • Dies kann für “statische” Klassen verwendet werden

    – Znarkus

    23. August 2009 um 9:41 Uhr

  • Siehe auch class_implements()

    – John Carter

    15. November 2011 um 21:54 Uhr

  • @therefromhere: Danke, guter Tipp. Das ist Teil der SPL-Erweiterung. Meine Antwort verwendete die Reflection-Erweiterung.

    – Bill Karwin

    15. November 2011 um 22:01 Uhr

  • Wenn Sie Namespaces verwenden, besteht keine Mehrdeutigkeit zwischen Schnittstellen und Klassen mit demselben Namen, und Sie können sie sicher verwenden instanceof wieder.

    – Grippe

    21. März 2012 um 16:18 Uhr


  • +1 für class_implements() da es offensichtlich schneller ist, class_implements und dann in_array aufzurufen, anstatt eine vollständige Reflexion vorzunehmen

    – Nikolaus

    17. März 2017 um 14:20 Uhr

Benutzer-Avatar
d.raev

Nur um zukünftige Suchen zu erleichtern ist_unterklasse_von ist auch eine gute Variante (für PHP 5.3.7+):

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

Benutzer-Avatar
SirPilan

Aktualisieren

Das is_a Funktion fehlt hier als Alternative.

Ich habe einige Leistungstests durchgeführt, um zu überprüfen, welche der angegebenen Methoden am leistungsfähigsten ist.

Ergebnisse über 100.000 Iterationen

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

Einige Punkte hinzugefügt, um den Unterschied tatsächlich zu “fühlen”.

Dadurch generiert: https://3v4l.org/8Cog7

Fazit

Falls Sie eine haben Objekt prüfen, verwenden instanceof wie in der akzeptierten Antwort erwähnt.

Falls Sie eine haben Klasse prüfen, verwenden is_a.

Bonus

In Anbetracht des Falls, dass Sie eine Klasse basierend auf einer Schnittstelle, die Sie benötigen, instanziieren möchten, ist dies besser zu verwenden is_a. Es gibt nur eine Ausnahme – wenn der Konstruktor leer ist.

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

Es wird zurückkehren bool. Der dritte Parameter “allow_string” ermöglicht es, Klassennamen zu überprüfen ohne Instanziieren der Klasse.

  • Das ist schön, hinzugefügt is_subclass_of zum Drehbuch. 3v4l.org/FY4re

    – Fegefeuer

    15. Dezember 2021 um 16:42 Uhr

Benutzer-Avatar
Starx

Sie können auch Folgendes tun

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

Es wird einen behebbaren Fehler auslösen, wenn die $objectSupposedToBeImplementing nicht umsetzt YourInterface Schnittstelle.

  • Das ist schön, hinzugefügt is_subclass_of zum Drehbuch. 3v4l.org/FY4re

    – Fegefeuer

    15. Dezember 2021 um 16:42 Uhr

1018580cookie-checkPrüfen, ob die Klasse einer Instanz eine Schnittstelle implementiert?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy