W3docs

instanceof

Узнайте, как оператор instanceof в PHP проверяет принадлежность объекта к классу, родительскому классу или интерфейсу — с примерами и подводными камнями.

Оператор PHP instanceof

instanceof — это оператор проверки типов в PHP. Он возвращает boolean (true или false), сообщая, принадлежит ли объект к заданному классу — или, что более полезно, принадлежит ли он к родительскому классу в цепочке наследования или реализует заданный интерфейс.

На этой странице рассматриваются синтаксис, поведение instanceof при наследовании и работе с интерфейсами, использование с именем класса в переменной, крайние случаи, которые часто удивляют (не-объекты, null, несуществующие имена классов), а также когда стоит применять instanceof, а когда лучше выбрать другой подход.

Если классы и объекты для вас в новинку, сначала прочитайте Классы и объекты PHP.

Синтаксис

$object instanceof ClassName

Выражение возвращает true, когда $object является экземпляром ClassName, любого класса, расширяющего ClassName, или любого класса, реализующего ClassName (когда ClassName — интерфейс). В противном случае возвращается false. Обратите внимание: синтаксис вызова метода отсутствует — instanceof является оператором, как и ===, а не функцией.

Базовая проверка

<?php

class MyClass {}
class MyOtherClass {}

$object = new MyClass();

if ($object instanceof MyClass) {
    echo "The object is an instance of MyClass.";
} else {
    echo "The object is not an instance of MyClass.";
}
// Output: The object is an instance of MyClass.

var_dump($object instanceof MyOtherClass);
// Output: bool(false)

$object был создан из MyClass, поэтому первая проверка возвращает true. С MyOtherClass он никак не связан, поэтому эта проверка даёт false. Оба класса не связаны между собой, даже если выглядят похоже.

instanceof и наследование

Главная ценность instanceof состоит в том, что он обходит всю цепочку наследования. Дочерний объект является экземпляром своего родительского класса, поэтому проверка проходит успешно для каждого предка.

<?php

class Fruit {}
class Apple extends Fruit {}
class Banana extends Fruit {}

$apple = new Apple();

var_dump($apple instanceof Apple);   // bool(true)  — its own class
var_dump($apple instanceof Fruit);   // bool(true)  — its parent class
var_dump($apple instanceof Banana);  // bool(false) — a sibling class

$apple проходит проверку Fruit, потому что Apple расширяет Fruit. Проверка Banana не проходит, потому что Apple и Banana — это «братские» классы: ни один из них не наследует другой. Подробнее в разделе Наследование PHP.

instanceof и интерфейсы

instanceof чаще всего используется с интерфейсами. Поскольку любой класс, реализующий интерфейс, считается его экземпляром, можно проверять наличие возможности, не беспокоясь о конкретном классе.

<?php

interface Drawable {
    public function draw(): string;
}

class Circle implements Drawable {
    public function draw(): string { return "○"; }
}

class Square implements Drawable {
    public function draw(): string { return "□"; }
}

$shapes = [new Circle(), new Square(), "not a shape"];

foreach ($shapes as $shape) {
    if ($shape instanceof Drawable) {
        echo $shape->draw();
    }
}
// Output: ○□

Строка "not a shape" пропускается, потому что не является Drawable. Это типичный сценарий использования: отфильтровать смешанный список до объектов, поддерживающих нужное поведение. Полная картина — в разделе Интерфейсы PHP.

Использование имени класса из переменной

В правой части может стоять строковая переменная с именем класса или интерфейса. Это удобно, когда тип определяется во время выполнения.

<?php

class Fruit {}
class Apple extends Fruit {}

$apple = new Apple();
$type  = 'Fruit';

var_dump($apple instanceof $type);   // bool(true)

Можно также сравнить два объекта — $a instanceof $b работает, когда $b является объектом: проверяется, является ли $a экземпляром класса $b.

Крайние случаи и подводные камни

instanceof никогда не выбрасывает исключений и не генерирует предупреждений. Если левый операнд не является объектом, оператор просто возвращает false.

<?php

class Fruit {}

var_dump(null instanceof Fruit);      // bool(false)
var_dump("Fruit" instanceof Fruit);   // bool(false) — a string is not an object
var_dump(42 instanceof Fruit);        // bool(false)

Это делает instanceof безопасным для использования в качестве защитной проверки перед вызовом метода — без необходимости предварительно вызывать is_object(). Если нужно только проверить, является ли значение объектом любого класса, используйте is_object().

Один тонкий момент: если передать несуществующее имя класса как строковый литерал в правой части, PHP не выполняет автозагрузку и не генерирует ошибку — просто возвращает false. Опечатка в имени класса провалится молча. По возможности предпочитайте прямое указание имени класса ($x instanceof Fruit) — тогда парсер сможет его проверить.

Когда использовать instanceof — и когда нет

Используйте instanceof, когда у вас действительно есть значение, тип которого нельзя гарантировать: данные из json_decode, смешанная коллекция, плагин из пользовательского кода или блок catch, сужающий тип исключения.

<?php

try {
    throw new InvalidArgumentException("bad input");
} catch (Exception $e) {
    if ($e instanceof InvalidArgumentException) {
        echo "Caught an argument error: " . $e->getMessage();
    }
}
// Output: Caught an argument error: bad input

Не стоит разбрасывать проверки instanceof по всему коду для ветвления по типу — длинные цепочки if ($x instanceof A) … elseif ($x instanceof B) обычно сигнализируют о том, что лучше определить метод в каждом классе и вызывать его полиморфно. Используйте instanceof для защиты операции, а не в качестве замены наследованию.

Краткое резюме

  • $object instanceof ClassName возвращает true, если объект является экземпляром класса, подкласса или реализованного интерфейса.
  • Оператор обходит всю цепочку наследования и сопоставляет интерфейсы — именно это делает его мощным инструментом.
  • Он возвращает false (но никогда не ошибку) для null, скалярных значений и прочих не-объектов, поэтому безопасен как защитная проверка.
  • Несуществующее имя класса в виде строки возвращает false без предупреждения; предпочитайте прямое указание имени класса.
  • Применяйте его для проверки типа неизвестного значения перед операцией — не как замену полиморфизму.

Практика

Практика
Для чего используется оператор 'instanceof' в PHP?
Для чего используется оператор 'instanceof' в PHP?
Was this page helpful?