В чем разница между is_a и instanceof?

Я знаю, что instanceof является оператором и is_a - это метод.

Является ли метод медленнее в производительности? Что вы предпочитаете использовать?

Ответ 1

Обновить

Начиная с PHP 5.3.9, функциональность is_a() изменилась. Исходный ответ ниже гласит, что is_a() должна принимать Object в качестве первого аргумента, но версии PHP> = 5.3.9 теперь принимают необязательный третий логический аргумент $allow_string (по умолчанию false), чтобы разрешить сравнения имен классов строк:

class MyBaseClass {}
class MyExtendingClass extends MyBaseClass {}

// Original behavior, evaluates to false.
is_a(MyExtendingClass::class, MyBaseClass::class);

// New behavior, evaluates to true.
is_a(MyExtendingClass::class, MyBaseClass::class, true);

Ключевое различие в новом поведении instanceof и is_a() заключается в том, что instanceof всегда проверяет, является ли цель экземпляром объекта указанного класса (включая расширяемые классы), тогда как is_a() требует, чтобы объект is_a() только тогда, когда $allow_string Аргумент $allow_string имеет значение по умолчанию false.


оригинал

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

Начиная с версии 5.3 он больше не считается устаревшим, поэтому здесь нет проблем.

Однако есть одно отличие. is_a принимает объект в качестве параметра 1, а строку (переменную, константу или литерал) - в качестве параметра 2. Итак:

is_a($object, $string); // <- Only way to call it

instanceof принимает объект в качестве параметра 1 и может принимать имя класса (переменную), экземпляр объекта (переменную) или идентификатор класса (имя класса записывается без кавычек) в качестве параметра 2.

$object instanceof $string;      // <- string class name
$object instanceof $otherObject; // <- object instance
$object instanceof ClassName;    // <- identifier for the class

Ответ 2

Ниже приведены результаты работы is_a() и instanceof:

Test name       Repeats         Result          Performance     
instanceof      10000           0.028343 sec    +0.00%
is_a()          10000           0.043927 sec    -54.98%

Источник тестирования здесь.

Ответ 3

instanceof может использоваться с другими экземплярами объекта, именем класса или интерфейсом. Я не думаю, что is_a() работает с интерфейсами (только строка, представляющая имя класса), но поправьте меня, если это так. (Обновление: см. Https://gist.github.com/1455148)

Пример с php.net:

interface MyInterface
{
}

class MyClass implements MyInterface
{
}

$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';

var_dump($a instanceof $b); // $b is an object of class MyClass
var_dump($a instanceof $c); // $c is a string 'MyClass'
var_dump($a instanceof $d); // $d is a string 'NotMyClass'

выходы:

bool(true)
bool(true)
bool(false)

Ответ 4

Что касается ответа ChrisF, is_a() больше не устарел с PHP 5.3.0. Я считаю, что всегда безопасно идти официальным источником таких вещей.

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

Кроме того, существует некоторая дискуссия о путанице вокруг отрицания проверки instanceof vs is_a(). Например, для instanceof вы бы сделали:

<?php
if( !($a instanceof A) ) { //... }
?>

vs для is_a():

<?php
if( !is_a($a, 'A' ) { //... }
?>

или

<?php
if( is_a($a, 'A') === FALSE) { //... }
?>

Изменить Похоже, что ChrisF удалил свой ответ, но первая часть моего ответа все еще стоит.

Ответ 5

Помимо скорости, еще одно важное отличие заключается в том, как они обрабатывают крайние случаи.

is_a($x1, $x2) // fatal error if x2 is not a string nor an object
$x1 instanceof $x2  // returns false even if $x2 is int, undefined, etc.

Итак, is_a() выделяет возможные ошибки, а instanceof подавляет их.

Ответ 6

Оптимизация минимальна. И микрооптимизации никогда не являются хорошим ответом перед читабельностью, понятностью и стабильностью кода.

(лично я предпочитаю экземпляр, но выбор за вами;))

Основное отличие заключается в возможности использования прямого имени класса с экземпляром

$экземпляр MyClass

короче

is_a ($ a, MyClass:: class)

(ok... его нетривиально.)

Синтаксическая окраска между instanceof (структура языка) и is_a тоже полезна (для меня). позволяя цвет функции более крупным операциям. И для однократного использования в if, instanceof dosnt нужно больше скобок.

Примечание: Конечно, вместо класса MyClass:: вы можете использовать более короткую прямую строку:

is_a ($ а, 'MyClass')

Но использование прямой строки в коде не является хорошей практикой.

Синтаксическая сортировка лучше и полезнее, если вы можете сделать разницу между простыми именами строк и классов. И проще сменить имена с постоянным именем класса. Специально, если вы используете пространство имен с псевдонимом.

Итак, wy использует is_a()?

Для того же уровня: читаемость и неопределенность. (Выбор ваш) Специально при использовании с ! или другими логическими операторами: is_a кажется более ориентированным со скобками.

if ($ a AND (! is_a ($ a, MyClass:: class) ИЛИ is_a ($ a, MyOtherClass:: class)))

более читаем, чем:

if ($ a AND (! ($ a instanceof MyClass) ИЛИ ($ a intanceof MyOtherClass)))

Другая веская причина - когда вам нужно использовать обратный вызов в функциях. (например, array_map...) instanceof isnt функция, ее языковая конструкция, поэтому вы не можете использовать ее как обратный вызов.

В этих случаях is_a может быть полезным

Ответ 7

Я не могу говорить о производительности - я еще ничего не измерил - но в зависимости от того, что вы пытаетесь, есть ограничения с instanceof. Запомните мой вопрос, совсем недавно, о нем:

PHP 'instanceof' не работает с константой класса

В итоге я использовал is_a. Мне нравится структура instanceof лучше (я думаю, что она читает лучше) и будет продолжать использовать ее там, где я могу.

Ответ 8

Ниже приведены результаты производительности, полученные здесь:

instanceof быстрее.

Функции

function method_1($a = null) { 
    return is_object($a) && is_a($a, 'Example');
}

function method_2($a = null) {
    return is_a((object) $a, 'Example');
}

function method_3($a = null) {
    return $a instanceof 'Example';
}

Время (по 5000 раз каждый)

0.00573397 // method_1(5) 
0.01437402 // method_2(5) 
0.00376201 // method_3(5)

Ответ 9

Существует сценарий, в котором работает только is_a() а instanceof завершится ошибкой.

instanceof ожидает буквальное имя класса или переменную, которая является либо объектом, либо строкой (с именем класса) в качестве правильного аргумента.

Но если вы хотите предоставить строку имени класса из вызова функции, это не сработает и приведет к синтаксической ошибке.

Тем не менее, тот же сценарий прекрасно работает с is_a().

Пример:

<?php

function getClassName() : string
{
    return "Foobar";
}

class Foobar
{
    private $xyz;

}

$x = new Foobar();

// this works of course
var_dump($x instanceof Foobar);

// this creates a syntax error
var_dump($x instanceof getClassName());

// this works
var_dump(is_a($x, getClassName()));

Это основано на PHP 7.2.14.