is_a和instanceof有什么区别?


205

我知道这instanceof是一个运算符,那is_a是一种方法。

该方法性能降低吗?您想使用什么?


15
is_a()可能会更慢-但是您可以使用call_user_func()调用它,而不能用这种方式调用instanceof ...
KamilTomšík2011年

Answers:


211

更新资料

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

36
为什么不推荐使用is_a
西奥多·史密斯

21
@ theodore-r-smith根据文档,它“ 未被
Janci 2012年

3
@danip$class = 'Foo'; var_dump($obj instanceof $class);
ircmaxell

39
is_avs instanceof运算符要注意的另一件事是,is_a它将接受第二个参数的表达式,而instanceof则不会。例如is_a($object, 'Prefix_'.$name)作品虽然$object instanceof 'Prefix_'.$name没有
埃文Purkhiser

6
is_a决不应该首先弃用。不过现在修复它有点晚了。问题在于instanceof操作符在PHP 4中引发语法错误,并且由于is_a在引入操作符的同一时间被弃用,因此就不可能在不抛出E_STRICT的情况下为PHP 4和5编写代码。您甚至无法做,if (version_compare(PHP_VERSION, 5) >= 0) { /* use instanceof */ } else { /* use is_a */ }因为它仍然会在PHP 4中引起语法错误
。– meustrus

47

这是is_a()instanceof的性能结果:

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

测试源在这里


6
换句话说,差异仅在需要每10000次使用节省约0.015秒时才重要。
CJ丹尼斯

1
截至php 7目前没有区别。
MAX

@CJDennis根据经验,当每个人都这样认为时,最终产品将比预期的慢。(软+操作系统+服务器未优化)。请记住,添加的时间并不总是线性的,而是可以是指数的。始终牢记性能。
Toto

@Toto有一篇很棒的博客文章,介绍了经验丰富的开发人员可以从初学者那里学到什么。希望您可以在右上角看到它。提防过早的优化!只有在时间问题变成问题后才能解决!如果性能可以接受,请不要花时间进行更改!
CJ Dennis

10

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)

3
is_a确实以与接口相同的方式工作instanceof(我想说同样的事情,但是我在提交之前已经对其进行了检查,并且确实可以工作)...
ircmaxell 2010年

2
-1请总结更新,而不只是链接到要点。这对尝试学习的人没有帮助。
埃里克·罗伯逊

5

关于ChrisF的答案,从PHP 5.3.0开始is_a() 不再推荐使用。我发现,像这样的事情经过官方消息来源总是比较安全的。

关于您的问题,丹尼尔(Daniel),我无法谈及性能差异,但是其中一部分将归因于可读性,您会发现它更易于使用。

另外,还有一些关于否定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则抑制了它们。


2

优化是最小的。在代码的可读性,可理解性和稳定性之前,微优化从来不是一个真正的好答案。

(我个人更喜欢instanceof,但是选择权是您自己决定的;))

主要区别在于可以将直接类名与instanceof一起使用

$ a MyClass的实例

短于

is_a($ a,MyClass :: class)

(好吧……这不是小事。)

instanceof(语言结构)和is_a之间的语法着色也很有用(对我而言)。让函数颜色进行更大的操作。对于if的单次使用,instanceof不需要更多的括号。

注意:当然可以使用较短的直接字符串代替MyClass :: class:

is_a($ a,'MyClass')

但是在代码中使用直接字符串并不是一个好习惯

如果可以在简单字符串和类名称之间进行区分,则语法上的匹配会更好,更有用。而且,使用常量类名更改名称更容易。特别是如果您使用带别名的名称空间。

因此,请使用is_a()吗?

同样的理由:可读性和不可理解性。(选择取决于您)与或其他布尔运算符:带括号的is_a似乎更实用。

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

比以下内容更具可读性:

if($ a AND(!($ Class MyClass的实例)或($ a intanceof MyOtherClass)))

另一个很好的理由是您需要在函数中使用回调。(例如array_map …) instanceof不是函数,而是一种语言构造,因此您不能将其用作回调。

在那些情况下,is_a可能有用



1

这是从此处获得的性能结果:

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)

1

在某些情况下,只有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。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.