Kann anhand einer Klasseninstanz festgestellt werden, ob eine bestimmte Schnittstelle implementiert ist? Soweit ich weiß, gibt es keine eingebaute Funktion, um dies direkt zu tun. Welche Optionen habe ich (falls vorhanden)?
interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
Sie können den Operator "instanceof" 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.
Wie therefromhere weist darauf hin, können Sie verwenden class_implements()
. Genau wie bei Reflection können Sie hiermit 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.
Siehe: http://php.net/manual/en/function.class-implements.php
Einige einfache Leistungstests zeigen die Kosten jedes Ansatzes:
Objektkonstruktion außerhalb der Schleife (100.000 Iterationen) ____________________________________________ | class_implements | Reflexion | instanceOf | | ------------------ | ------------ | ------------ | | 140 ms | 290 ms | 35 ms | '----------------------------------------' Objektkonstruktion innerhalb der Schleife (100.000 Iterationen) ____________________________________________ | class_implements | Reflexion | instanceOf | | ------------------ | ------------ | ------------ | | 182 ms | 340 ms | 83 ms | Billiger Konstruktor | 431 ms | 607 ms | 338 ms | Teurer Konstruktor '----------------------------------------'
100.000 Iterationen ____________________________________________ | class_implements | Reflexion | 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 diesem einfachen Code .
nlaq weist darauf hin, dass damit getestet werden instanceof
kann, ob das Objekt eine Instanz einer Klasse ist, die eine Schnittstelle implementiert.
Aber instanceof
unterscheidet nicht zwischen einem Klasse - Typ und einer Schnittstelle. Sie wissen nicht, ob das Objekt eine Klasse ist , die zufällig aufgerufen wird IInterface
.
Sie können auch die Reflection-API in PHP verwenden, um dies genauer zu testen:
$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
print "Yep!\n";
}
class_implements()
instanceof
wieder verwenden.class_implements()
da es offensichtlich schneller ist, class_implements und dann in_array aufzurufen, anstatt eine vollständige Reflexion zu machenNur um zukünftige Suchen zu erleichtern, ist is_subclass_of auch eine gute Variante (für PHP 5.3.7+):
quelle
Sie können auch Folgendes tun
Es wird ein behebbarer Fehler ausgegeben, wenn die Schnittstelle
$objectSupposedToBeImplementing
nicht implementiert wirdYourInterface
.quelle
Aktualisieren
Die
is_a
Funktion fehlt hier alternativ.Ich habe einige Leistungstests durchgeführt, um zu überprüfen, welche der angegebenen Methoden am leistungsfähigsten ist.
Ergebnisse über 100.000 Iterationen
Es wurden einige Punkte hinzugefügt, um den Unterschied tatsächlich zu "fühlen".
Generiert von diesem: https://3v4l.org/8Cog7
Fazit
Wenn Sie ein zu überprüfendes Objekt haben , verwenden Sie es
instance of
wie in der akzeptierten Antwort angegeben.Wenn Sie eine Klasse überprüfen müssen, verwenden Sie
is_a
.Bonus
In dem Fall, dass Sie eine Klasse basierend auf einer Schnittstelle instanziieren möchten, die Sie benötigen, ist ihre Verwendung vorformender
is_a
. Es gibt nur eine Ausnahme - wenn der Konstruktor leer ist.Beispiel:
is_a(<className>, <interfaceName>, true);
Es wird zurückkehren
bool
. Mit dem dritten Parameter " allow_string " können Klassennamen überprüft werden, ohne die Klasse zu instanziieren.quelle