2024年PHP开发者大会日本站

类型运算符

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)

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

示例 #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 条注释

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
16 年前
示例 #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
16 年前
可以使用“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
7 年前
如果要使用“$foo instanceof $bar”来确定两个对象是否属于同一个类,请记住,“instanceof”在 $foo 是 $bar 类_子类_的实例时也会评估为 true。

如果确实要查看它们是否属于_同一个_类,则它们都必须是彼此类的实例。也就是说
<?php

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

?>

可以将其视为“get_class($bar) == get_class($foo)”的替代方法,它避免了通过字符串查找和比较的迂回。
fbableus
13年前
如果要测试类名是否是类的实例,则 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 年前
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年前
使用未定义的变量会导致错误。

如果变量存疑,必须预先限定

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