Czy przy danej instancji klasy można określić, czy implementuje ona określony interfejs? O ile wiem, nie ma wbudowanej funkcji, która mogłaby to zrobić bezpośrednio. Jakie mam opcje (jeśli w ogóle)?
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 refleksjiAby ułatwić przyszłe wyszukiwania, is_subclass_of jest również dobrym wariantem (dla PHP 5.3.7+):
źródło
Możesz także wykonać następujące czynności
Jeśli interfejs
$objectSupposedToBeImplementing
nie zaimplementujeYourInterface
interfejsu, zostanie wyświetlony możliwy do naprawienia błąd .źródło
Aktualizacja
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.
Wyniki ponad 100 tys. Iteracji
Dodano kilka kropek, aby faktycznie „poczuć” różnicę.
Wygenerowane przez to: https://3v4l.org/8Cog7
Wniosek
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
.Premia
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.źródło