类型运算符

instanceof 用于确定 PHP 变量是否为某个 的实例化对象

示例 #1 使用 instanceof 和类

<?php
class MyClass
{
}

class
NotMyClass
{
}
$a = new MyClass;

var_dump($a instanceof MyClass);
var_dump($a instanceof NotMyClass);
?>

上面的例子将输出

bool(true)
bool(false)

instanceof 也可以用来确定一个变量是否是一个从父类继承的类的实例化对象

示例 #2 使用 instanceof 和继承的类

<?php
class ParentClass
{
}

class
MyClass extends ParentClass
{
}

$a = new MyClass;

var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>

上面的例子将输出

bool(true)
bool(true)

要检查一个对象是否 *不是* 一个类的实例,可以使用 逻辑 not 运算符

示例 #3 使用 instanceof 检查对象是否 *不是* 一个类的实例

<?php
class MyClass
{
}

$a = new MyClass;
var_dump(!($a instanceof stdClass));
?>

上面的例子将输出

bool(true)

最后,instanceof 也可以用来确定一个变量是否是一个实现 接口 的类的实例化对象

示例 #4 使用 instanceof 和接口

<?php
interface MyInterface
{
}

class
MyClass implements MyInterface
{
}

$a = new MyClass;

var_dump($a instanceof MyClass);
var_dump($a instanceof MyInterface);
?>

上面的例子将输出

bool(true)
bool(true)

虽然 instanceof 通常与文字类名一起使用,但它也可以与其他对象或字符串变量一起使用

示例 #5 使用 instanceof 和其他变量

<?php
interface MyInterface
{
}

class
MyClass implements MyInterface
{
}

$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';

var_dump($a instanceof $b); // $b 是 MyClass 类的一个对象
var_dump($a instanceof $c); // $c 是一个字符串 'MyClass'
var_dump($a instanceof $d); // $d 是一个字符串 'NotMyClass'
?>

上面的例子将输出

bool(true)
bool(true)
bool(false)

如果被测试的变量不是一个对象,instanceof 不会抛出任何错误,它只是返回 false。 然而,在 PHP 7.3.0 之前,常量是不允许的。

示例 #6 使用 instanceof 测试其他变量

<?php
$a
= 1;
$b = NULL;
$c = imagecreate(5, 5);
var_dump($a instanceof stdClass); // $a 是一个整数
var_dump($b instanceof stdClass); // $b 是 NULL
var_dump($c instanceof stdClass); // $c 是一个资源
var_dump(FALSE instanceof stdClass);
?>

上面的例子将输出

bool(false)
bool(false)
bool(false)
PHP Fatal error:  instanceof expects an object instance, constant given

从 PHP 7.3.0 开始,常量可以在 instanceof 运算符的左侧使用。

示例 #7 使用 instanceof 测试常量

<?php
var_dump
(FALSE instanceof stdClass);
?>

上面例子在 PHP 7.3 中的输出

bool(false)

从 PHP 8.0.0 开始,instanceof 现在可以与任意表达式一起使用。 表达式必须用括号括起来,并产生一个 字符串

示例 #8 使用 instanceof 和任意表达式

<?php

class ClassA extends \stdClass {}
class
ClassB extends \stdClass {}
class
ClassC extends ClassB {}
class
ClassD extends ClassA {}

function
getSomeClass(): string
{
return
ClassA::class;
}

var_dump(new ClassA instanceof ('std' . 'Class'));
var_dump(new ClassB instanceof ('Class' . 'B'));
var_dump(new ClassC instanceof ('Class' . 'A'));
var_dump(new ClassD instanceof (getSomeClass()));
?>

在 PHP 8 中,以上示例的输出

bool(true)
bool(true)
bool(false)
bool(true)

instanceof 运算符有一个功能变体,使用 is_a() 函数。

添加注释

用户贡献注释 16 notes

jphaas at gmail dot com
17 年前
发布此内容是为了使“typeof”一词出现在此页面上,以便在谷歌搜索“php typeof”时此页面能够显示出来。......没错,前 Java 用户。
knarlin at yahoo dot com dot au
11 年前
检查对象是否不是类的实例,示例 #3 使用了多余的括号。

<?php
var_dump
(!($a instanceof stdClass));
?>

因为 instanceof 的运算符优先级高于 !,你可以直接使用

<?php
var_dump
( ! $a instanceof stdClass );
?>
dava
10 年前
你也可以使用 instanceOf 比较两个对象。在这种情况下,instanceOf 将比较两个对象的类型。这在某些情况下非常有用。

<?php

class A { }
class
B { }

$a = new A;
$b = new B;
$a2 = new A;

echo
$a instanceOf $a; // true
echo $a instanceOf $b; // false
echo $a instanceOf $a2; // true

?>
Sudarshan Wadkar
12 年前
我没有看到此页面上提到“命名空间”,所以我想我会插一句。当您将 instanceof 运算符的第二个操作数作为字符串而不是简单的类名传递时,它将接受 FQCN。即使您在顶层有 `use MyNamespace\Bar;`,它也不会解析。以下是我想表达的意思。

## testinclude.php ##
<?php
namespace Bar1;
{
class
Foo1{ }
}
namespace
Bar2;
{
class
Foo2{ }
}
?>
## test.php ##
<?php
include('testinclude.php');
use
Bar1\Foo1 as Foo;
$foo1 = new Foo(); $className = 'Bar1\Foo1';
var_dump($foo1 instanceof Bar1\Foo1);
var_dump($foo1 instanceof $className);
$className = 'Foo';
var_dump($foo1 instanceof $className);
use
Bar2\Foo2;
$foo2 = new Foo2(); $className = 'Bar2\Foo2';
var_dump($foo2 instanceof Bar2\Foo2);
var_dump($foo2 instanceof $className);
$className = 'Foo2';
var_dump($foo2 instanceof $className);
?>
## stdout ##
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
bool(false)
wapinet at mail dot ru
3 年前
如果您只有类名(而不是对象),可以使用此代码段:https://3v4l.org/mUKUC
<?php
interface i{}
class
a implements i{}

var_dump(a::class instanceof i); // false
var_dump(in_array(i::class, class_implements(a::class), true)); // true
wadih at creationmw dot com
7 年前
在命名空间内部执行 $a instanceof stdClass 将无法正常工作。

您需要执行

<?php
if ($a instanceof \stdClass)
?>
kevin dot benton at beatport dot com
15 年前
示例 #5 也可以扩展为包括...

var_dump($a instanceof MyInterface);

新的结果将是

bool(true)

因此,instanceof 足够智能,可以知道实现接口的类是接口的实例,而不仅仅是类的实例。我在上面的解释中没有看到这一点被足够清晰地说明。
wbcarts at juno dot com
12 年前
对 instanceof 运算符的简单、清晰、明了的用法

首先,定义几个简单的 PHP 对象来操作——我将引入 Circle 和 Point。以下是两个类的定义

<?php

class Circle
{
protected
$radius = 1.0;

/*
* 这是我们将在下面使用 instanceof 运算符的原因。
*/
public function setRadius($r)
{
$this->radius = $r;
}

public function
__toString()
{
return
'Circle [radius=' . $this->radius . ']';
}
}

class
Point
{
protected
$x = 0;
protected
$y = 0;

/*
* 这是我们将在下面使用 instanceof 运算符的原因。
*/
public function setLocation($x, $y)
{
$this->x = $x;
$this->y = $y;
}

public function
__toString()
{
return
'Point [x=' . $this->x . ', y=' . $this->y . ']';
}
}

?>

现在实例化几个这些类型的实例。注意,我将把它们放在数组(集合)中,以便我们可以快速迭代它们。

<?php

$myCollection
= array(123, 'abc', 'Hello World!',
new
Circle(), new Circle(), new Circle(),
new
Point(), new Point(), new Point());

$i = 0;
foreach(
$myCollection AS $item)
{
/*
* setRadius() 函数在上面的 Circle 类定义中编写,
* 所以在调用它之前确保 $item 是 Circle 类型的实例,
* 并且避免 PHP 问题!
*/
if($item instanceof Circle)
{
$item->setRadius($i);
}

/*
* setLocation() 函数在上面的 Point 类定义中编写,
* 所以在调用它之前确保 $item 是 Point 类型的实例,
* 并且避免陷入错误!
*/
if($item instanceof Point)
{
$item->setLocation($i, $i);
}

echo
'$myCollection[' . $i++ . '] = ' . $item . '<br>';
}

?>

$myCollection[0] = 123
$myCollection[1] = abc
$myCollection[2] = Hello World!
$myCollection[3] = Circle [radius=3]
$myCollection[4] = Circle [radius=4]
$myCollection[5] = Circle [radius=5]
$myCollection[6] = Point [x=6, y=6]
$myCollection[7] = Point [x=7, y=7]
$myCollection[8] = Point [x=8, y=8]
jtaal at eljakim dot nl
15 年前
您可以使用“self”来引用当前类

<?php
class myclass {
function
mymethod($otherObject) {
if (
$otherObject instanceof self) {
$otherObject->mymethod(null);
}
return
'works!';
}
}

$a = new myclass();
print
$a->mymethod($a);
?>
Hayley Watson
6 years ago
如果您想使用“$foo instanceof $bar”来确定两个对象是否属于同一个类,请记住“instanceof”在 $foo 是 $bar 类的一个_子类_的实例时也会返回真。

如果您真的想查看它们是否属于_同一个_类,那么它们必须都是对方类的实例。也就是说
<?php

($foo instanceof $bar && $bar instanceof $foo)

?>

将其视为“get_class($bar) == get_class($foo)”的替代方法,它避免了字符串查找和比较的绕行。
fbableus
13 years ago
如果您想测试一个类名是否为某个类的实例,instanceof 运算符将不起作用。

<?php
$classname
= 'MyClass';
if(
$classname instanceof MyParentClass) echo 'Child of it';
else echo
'Not child of it';
?>

将始终输出
Not child of it

您必须使用 ReflectionClass
<?php
$classname
= 'MyClass';
$myReflection = new ReflectionClass($classname);
if(
$myReflection->isSubclassOf('MyParentClass')) echo 'Child of it';
else echo
'Not child of it';
?>

将输出正确的结果。
如果您正在测试接口,请使用 implementsInterface() 而不是 isSublassOf()。
julien plee using g mail dot com
17 年前
回复 vinyanov at poczta dot onet dot pl

您提到了“instanceof 运算符不接受字符串作为其第一个操作数”。然而,这种行为是完全正确的,因此,您误解了实例的含义。

<?php 'ClassA' instanceof 'ClassB'; ?> 的意思是“名为 ClassA 的类是名为 ClassB 的类的实例”。这是一个毫无意义的句子,因为当您实例化一个类时,您总是会得到一个对象。因此,您只能询问一个对象是否是某个类的实例。

我认为询问“ClassA 是否属于 ClassB”(或“ClassA 是 (类型) ClassB 的类”)甚至“ClassA 是 (也) ClassB”更合适。但第一个没有实现,而第二个只适用于对象,就像 instanceof 运算符一样。

此外,我刚刚测试了您的代码,它绝对没有像 instanceof 一样(扩展到类)!我不建议任何人重用它。使用 <?php is_instance_of ($instanceOfA, 'ClassB'); ?> 会在使用 __autoload 时引发警告“include_once(Object id #1.php) …”(尝试将 $instanceOfA 视为类名来查找)。

最后,这里有一个快速(对我来说)的示例函数代码,用于验证对象或类

<?php
function kind_of (&$object_or_class, $class)
{
return
is_object ($object_or_class) ?
$object_or_class instanceof $class
: (is_subclass_of ($object_or_class $class)
||
strtolower ($object_or_class) == strtolower ($class));
}
?>
ejohnson82 at gmail dot com
16 years ago
PHP 解析器在以下两行中任何一行上都会生成解析错误。
显然,“instanceof”结构可以在第二个位置接受一个字符串变量,但它_不会_接受一个字符串... 太糟糕了

class Bar {}
$b = new Bar;
$b_class = "Bar";
var_export($b instanceof Bar); // 这没问题
var_export($b instanceof $b_class); // 这没问题
//var_export($f instanceof "Bar"); // 这在语法上是非法的
//var_export($f instanceof 'Bar'); // 这在语法上是非法的
ASchmidt at Anamera dot net
4 years ago
使用未定义的变量会导致错误。

如果变量有疑问,必须进行预先限定

if ( isset( $MyInstance ) and $MyInstance instanceof MyClass ) ...
jeanyves dot terrien at orange-ftgroup dot com
17 年前
跨版本函数,即使您在 php4 中工作
(instanceof 是 php4 中未定义的运算符)

function isMemberOf($classename) {
$ver = floor(phpversion());
if($ver > 4) {
$instanceof = create_function ('$obj,$classname','return $obj instanceof $classname;');
return $instanceof($this,$classname);
} else {
// Php4 使用小写字母作为类名。
return is_a($this, strtolower($classname));
}
} // end function isMemberOf
soletan at toxa dot de
17 年前
请注意:!= 是一个独立的运算符,具有独立的语义。从语言语法的角度来看,否定一个运算符有点荒谬。当然,可以否定函数的结果(比如 is_a()),因为它没有否定函数本身或其语义。

instanceof 是一个二元运算符,因此像这样在二进制术语中使用

terma instanceof termb

而 ! (否定) 是一个一元运算符,因此可以应用于单个术语,像这样

!term

并且一个术语永远不包含运算符,只有!任何语言中都没有这样的结构(请纠正我!)。但是,instanceof 最终并不像否定那样在每个操作数位置(上面的“terma”或“termb”)中支持嵌套项

!!!!!!!!!!!!!!term == term

所以回到原点,您是否曾经写过

a !!!!!!!!!!!!= b

来测试等价性?
To Top