Я знаю, що 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()вимагає лише об'єкта, коли об'єкт $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_avs, instanceofце те, що is_aбуде приймати вирази для другого параметра, в той час як instanceof wont. Наприклад, 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) { //... }
?>
Edit Схоже, 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
$ екземпляр MyClass
коротше, ніж
is_a ($ a, MyClass :: клас)
(добре ... це не банально.)
Синтаксичне забарвлення між instanceof (мовна структура) та is_a також корисне (для мене). надаючи функціональний колір більшій операції. І для одноразового використання, якщо, instanceof не потребує більше дужок.
Примітка. Звичайно, замість MyClass :: class ви можете використовувати коротший прямий рядок:
is_a ($ a, "MyClass")
Але використовувати прямий рядок у коді не є хорошою практикою .
Синтаксичне зібрання є кращим і кориснішим, якщо ви можете змінити назви простих рядків і класів. І простіше міняти імена з постійним іменем класу. Спеціально, якщо ви використовуєте простір імен з псевдонімом.
Отож, як використовувати is_a () ?
З тієї ж причини: читабельність та невідчутність. (вибір за вами) Спеціальність при використанні ! або інші булеві оператори: is_a здається більш вдалим з дужками.
if ($ a AND (! is_a ($ a, MyClass :: class) OR is_a ($ a, MyOtherClass :: class)))
читабельніше, ніж:
if ($ a AND (! ($ екземпляр MyClass) АБО ($ intance 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.