我知道这instanceof
是一个运算符,那is_a
是一种方法。
该方法性能降低吗?您想使用什么?
我知道这instanceof
是一个运算符,那is_a
是一种方法。
该方法性能降低吗?您想使用什么?
Answers:
更新资料
从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_a
vs instanceof
运算符要注意的另一件事是,is_a
它将接受第二个参数的表达式,而instanceof则不会。例如is_a($object, 'Prefix_'.$name)
作品虽然$object instanceof 'Prefix_'.$name
没有
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中引起语法错误
这是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的答案,从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删除了他的答案,但答案的第一部分仍然有效。
除了速度之外,另一个重要的区别是它们处理边缘案例的方式。
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之间的语法着色也很有用(对我而言)。让函数颜色进行更大的操作。对于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可能有用
我无法说出性能-我还没有评估过任何东西-但是根据您的尝试,会受到一些限制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。