Odpowiedzi:
interface IInterface
{
}
class TheClass implements IInterface
{
}
$cls = new TheClass();
if ($cls instanceof IInterface) {
echo "yes";
}
Możesz użyć operatora „instanceof”. Aby go użyć, lewy operand jest instancją klasy, a prawy operand jest interfejsem. Zwraca prawdę, jeśli obiekt implementuje określony interfejs.
Jak stąd wynika , możesz użyć class_implements()
. Podobnie jak w przypadku Reflection, pozwala to określić nazwę klasy jako ciąg i nie wymaga instancji klasy:
interface IInterface
{
}
class TheClass implements IInterface
{
}
$interfaces = class_implements('TheClass');
if (isset($interfaces['IInterface'])) {
echo "Yes!";
}
class_implements()
jest częścią rozszerzenia SPL.
Zobacz: http://php.net/manual/en/function.class-implements.php
Niektóre proste testy wydajności pokazują koszty każdego podejścia:
Konstrukcja obiektu poza pętlą (100 000 iteracji) ____________________________________________ | narzędzia_klasy | Odbicie | instanceOf | | ------------------ | ------------ | ------------ | | 140 ms | 290 ms | 35 ms | „--------------------------------------------” Konstrukcja obiektu wewnątrz pętli (100 000 iteracji) ____________________________________________ | narzędzia_klasy | Odbicie | instanceOf | | ------------------ | ------------ | ------------ | | 182 ms | 340 ms | 83 ms | Tani konstruktor | 431 ms | 607 ms | 338 ms | Drogi konstruktor „--------------------------------------------”
100 000 iteracji ____________________________________________ | narzędzia_klasy | Odbicie | instanceOf | | ------------------ | ------------ | ------------ | | 149 ms | 295 ms | Nie dotyczy | „--------------------------------------------”
Gdzie kosztowna __construct () to:
public function __construct() {
$tmp = array(
'foo' => 'bar',
'this' => 'that'
);
$in = in_array('those', $tmp);
}
Te testy są oparte na tym prostym kodzie .
nlaq wskazuje, że instanceof
można go użyć do sprawdzenia, czy obiekt jest instancją klasy implementującej interfejs.
Ale instanceof
nie rozróżnia między typem klasy a interfejsem. Nie wiesz, czy obiekt jest klasą, która została wywołana IInterface
.
Możesz również użyć interfejsu API odbicia w PHP, aby przetestować to bardziej szczegółowo:
$class = new ReflectionClass('TheClass');
if ($class->implementsInterface('IInterface'))
{
print "Yep!\n";
}
class_implements()
instanceof
ponownie.
class_implements()
ponieważ jest oczywiście szybsze wywołanie class_implements, a następnie in_array, zamiast dokonywać pełnej refleksji
Aby ułatwić przyszłe wyszukiwania, is_subclass_of jest również dobrym wariantem (dla PHP 5.3.7+):
if (is_subclass_of($my_class_instance, 'ISomeInterfaceName')){
echo 'I can do it!';
}
is_a
Funkcja brakuje tutaj jako alternatywę.
Zrobiłem kilka testów wydajności, aby sprawdzić, który z podanych sposobów jest najbardziej wydajny.
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% | ............................................
Dodano kilka kropek, aby faktycznie „poczuć” różnicę.
Wygenerowane przez to: https://3v4l.org/8Cog7
Jeśli masz obiekt do sprawdzenia, użyj tego, co instance of
podano w zaakceptowanej odpowiedzi.
Jeśli masz klasę do sprawdzenia, użyj is_a
.
Biorąc pod uwagę przypadek, w którym chcesz utworzyć instancję klasy w oparciu o interfejs, którego potrzebujesz, jest to bardziej wydajne w użyciu is_a
. Jest tylko jeden wyjątek - gdy konstruktor jest pusty.
Przykład:
is_a(<className>, <interfaceName>, true);
Wróci bool
. Trzeci parametr „ allow_string ” umożliwia sprawdzanie nazw klas bez tworzenia instancji klasy.