語法與用途
$object instanceof ClassName
$object instanceof InterfaceName
$object instanceof ParentClass // 繼承關係也會 true
- **不需引號**包裹類別名稱(字串會語法錯誤)
- 回傳
bool,可直接用於 if、switch、三元運算子
- 檢查三件事:具體類別實例、子類別實例、實作介面
基礎範例
class Employee {}
class Manager extends Employee {}
class Contractor implements WorkerInterface {}
$manager = new Manager();
$contractor = new Contractor();
var_dump($manager instanceof Employee); // true (繼承)
var_dump($manager instanceof Manager); // true (自身)
var_dump($contractor instanceof WorkerInterface); // true (介面)
var_dump($manager instanceof WorkerInterface); // false
進階場景:多型分派替代 switch
function processPayment(PaymentMethod $method) {
// 不推薦:用 instanceof 分派
if ($method instanceof CreditCard) { ... }
elseif ($method instanceof PayPal) { ... }
// 推薦:多型 $method->pay()
}
// 若必須外部判斷 (如序列化、路由)
$handlerMap = [
CreditCard::class => fn($m) => $m->charge(),
PayPal::class => fn($m) => $m->redirect(),
];
$handler = $handlerMap[get_class($method)] ?? fn($m) => throw new \Exception('不支援');
$handler($method);
instanceof vs is_subclass_of() 關鍵差異
class Foo {}
class Bar extends Foo {}
$a = new Foo();
$b = new Bar();
var_dump($a instanceof Foo); // true
var_dump($b instanceof Foo); // true
var_dump($a instanceof Bar); // false
var_dump($b instanceof Bar); // true
var_dump(is_subclass_of($a, 'Foo')); // false (自身不算子類)
var_dump(is_subclass_of($b, 'Foo')); // true
var_dump(is_subclass_of($a, 'Bar')); // false
var_dump(is_subclass_of($b, 'Bar')); // false
| 特性 | instanceof | is_subclass_of() |
| 檢查對象 | 物件實例 | 類別名稱 (字串) 或物件 |
| 自身類別 | true | false |
| 父類別 | true | true |
| 介面 | 支援 | 不支援 (需 implements_interface()) |
| 字串類別名 | 不支援 (需 $obj instanceof $className 動態) | 支援 |
動態類別名稱檢查
$className = 'Manager';
$obj = new Manager();
// 正確寫法
if ($obj instanceof $className) { ... }
// 錯誤寫法 (字串當類別常數)
if ($obj instanceof '$className') { ... } // Parse error
實用工具函數:多型別檢查
function isInstanceOf($object, array $types): bool {
foreach ($types as $type) {
if (is_string($type)) {
if ($object instanceof $type) return true;
} elseif (is_object($type)) {
if ($object instanceof get_class($type)) return true;
}
}
return false;
}
// 使用
if (isInstanceOf($user, [Admin::class, Editor::class, 'PremiumInterface'])) {
// 權限通過
}
常見誤區
- 用於非物件:
null instanceof Foo 永遠 false,不會報錯
- 介面名稱衝突:類別與介面同名時,
instanceof 優先匹配類別
- Trait 不計入:
use MyTrait 的類別 instanceof MyTrait 為 false (PHP 8.1+ 可用 trait_exists 配合反射)