Я знаю, что instanceof
это оператор, а is_a
это метод.
Является ли метод медленнее в производительности? Что бы вы предпочли использовать?
Я знаю, что instanceof
это оператор, а is_a
это метод.
Является ли метод медленнее в производительности? Что бы вы предпочли использовать?
Ответы:
Обновить
Начиная с PHP 5.3.9 , функциональность is_a()
изменилась. Исходный ответ ниже гласит, что в качестве первого аргумента is_a()
необходимо принять 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()
требуется только создание экземпляра объекта, когда для $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
недооценен?
$class = 'Foo'; var_dump($obj instanceof $class);
is_a
В.С. instanceof
оператор , который is_a
принимает выражения для второго параметра, в то время как InstanceOf привычка. Например, is_a($object, 'Prefix_'.$name)
работает, а $object instanceof 'Prefix_'.$name
не
is_a
никогда не должен был быть осужден в первую очередь. Сейчас немного поздно это исправить. Проблема заключается в том, что instanceof
оператор генерирует синтаксические ошибки в PHP 4, и, поскольку он is_a
был объявлен устаревшим в то же время, когда был введен оператор, стало невозможно писать код для PHP 4 и 5 без использования E_STRICT. Вы даже не можете сделать это, if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }
потому что это все равно вызовет синтаксическую ошибку в PHP 4.
Вот результаты производительности is_a () и instanceof :
Test name Repeats Result Performance
instanceof 10000 0.028343 sec +0.00%
is_a() 10000 0.043927 sec -54.98%
Источник теста здесь .
php 7
нет никакой разницы.
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)
is_a
работает с интерфейсами так же, как instanceof
(я собирался сказать то же самое, но я проверял это перед отправкой, и это действительно работает) ...
Что касается ответа ChrisF, is_a()
больше не считается устаревшим с PHP 5.3.0. Я считаю, что для таких вещей всегда безопаснее обращаться к официальному источнику.
Что касается вашего вопроса, Дэниел, я не могу сказать о различиях в производительности, но отчасти это сводится к удобочитаемости, с которой вам легче работать.
Кроме того, есть некоторая дискуссия о путанице вокруг отрицания instanceof
проверки против is_a()
. Например, для instanceof
вас сделали бы:
<?php
if( !($a instanceof A) ) { //... }
?>
против следующего для 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 их подавляет.
Оптимизация минимальна. И микрооптимизация никогда не будет действительно хорошим ответом перед читабельностью, понятностью и стабильностью кода.
(лично я предпочитаю instanceof , но выбор за вами;))
Принципиальным отличием является возможность использования прямого имени класса с instanceof
$ a экземпляра MyClass
короче чем
is_a ($ a, MyClass :: class)
(хорошо ... это не тривиально.)
Синтаксическая окраска между instanceof (структура языка) и is_a также полезна (для меня). позволяя функции цвета для больших операций. И для однократного использования в случае, если экземпляр не нуждается в дополнительных скобках.
Примечание. Конечно, вместо MyClass :: class вы можете использовать более короткую прямую строку:
is_a ($ а, 'MyClass')
Но использование прямой строки в коде не очень хорошая практика .
Синтаксическая раскраска лучше и полезнее, если вы можете различать простые имена строк и классов. И легче поменять имена с постоянным именем класса. Специально, если вы используете пространство имен с псевдонимом.
Так зачем использовать is_a () ?
Для того же смысла: читабельность и непонятность. (выбор за вами) Специально при использовании с ! или другие логические операторы: is_a кажется более практичным с круглыми скобками.
if ($ a AND (! is_a ($ a, MyClass :: class) ИЛИ is_a ($ a, MyOtherClass :: class)))
более читабельно, чем:
if ($ a AND (! ($ a экземпляра MyClass) ИЛИ ($ a intance of MyOtherClass)))
Другая хорошая причина - когда вам нужно использовать обратный вызов в функциях. (например, array_map …) instanceof - это не функция, это языковая конструкция, поэтому вы не можете использовать ее в качестве обратного вызова.
В этих случаях 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.