Я знаю, что instanceof
является оператором и is_a
- это метод.
Является ли метод медленнее в производительности? Что вы предпочитаете использовать?
Я знаю, что instanceof
является оператором и is_a
- это метод.
Является ли метод медленнее в производительности? Что вы предпочитаете использовать?
Обновить
Начиная с 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
Ниже приведены результаты работы is_a() и instanceof:
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
Источник тестирования здесь.
instanceof
может использоваться с другими экземплярами объекта, именем класса или интерфейсом. Я не думаю, что (Обновление: см. Https://gist.github.com/1455148)is_a()
работает с интерфейсами (только строка, представляющая имя класса), но поправьте меня, если это так.
Пример с 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)
Что касается ответа 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 удалил свой ответ, но первая часть моего ответа все еще стоит.
Помимо скорости, еще одно важное отличие заключается в том, как они обрабатывают крайние случаи.
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 подавляет их.
Оптимизация минимальна. И микрооптимизации никогда не являются хорошим ответом перед читабельностью, понятностью и стабильностью кода.
(лично я предпочитаю экземпляр, но выбор за вами;))
Основное отличие заключается в возможности использования прямого имени класса с экземпляром
$экземпляр 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 может быть полезным
Я не могу говорить о производительности - я еще ничего не измерил - но в зависимости от того, что вы пытаетесь, есть ограничения с instanceof
. Запомните мой вопрос, совсем недавно, о нем:
PHP 'instanceof' не работает с константой класса
В итоге я использовал is_a
. Мне нравится структура instanceof
лучше (я думаю, что она читает лучше) и будет продолжать использовать ее там, где я могу.
Ниже приведены результаты производительности, полученные здесь:
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)
Существует сценарий, в котором работает только 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.