PHPでは、 IS_A関数を使用して、オブジェクトがクラスのインスタンスかそのサブクラスかを判断します。タイプの検出に非常に適しています。ただし、より柔軟で拡張可能なタイプの裁判官を書きたい場合は、閉鎖(匿名関数)を組み合わせて動的な判断ロジックを実装し、それにより、ステートメントを切り替えるか切り替えた場合の重複を書くことを避けることができます。
閉鎖と組み合わせたIS_A関数を使用して、柔軟なタイプジャッジを作成する方法を段階的に見てみましょう。
<?php
class Animal {}
class Dog extends Animal {}
$dog = new Dog();
var_dump(is_a($dog, 'Dog')); // bool(true)
var_dump(is_a($dog, 'Animal')); // bool(true)
var_dump(is_a($dog, 'Cat')); // bool(false)
?>
IS_Aは、オブジェクトが特定のクラスまたはそのサブクラスのインスタンスであるかどうかを判断でき、タイプを判断するための基礎を提供します。
閉鎖を使用して異なる判断ルールを定義し、統一されたインターフェイスでそれらを呼び出すことができます。
<?php
$typeCheckers = [
'dog' => function($obj) {
return is_a($obj, 'Dog');
},
'animal' => function($obj) {
return is_a($obj, 'Animal');
},
'string' => function($obj) {
return is_string($obj);
}
];
// 使用の例
function checkType($obj, $type, $checkers) {
if (!isset($checkers[$type])) {
throw new InvalidArgumentException("不明なタイプ: $type");
}
return $checkers[$type]($obj);
}
$dog = new Dog();
var_dump(checkType($dog, 'dog', $typeCheckers)); // bool(true)
var_dump(checkType($dog, 'animal', $typeCheckers)); // bool(true)
var_dump(checkType("hello", 'string', $typeCheckers));// bool(true)
?>
このようにして、新しいタイプの判断を追加するには、 $ TypeCheckersアレイに閉鎖を追加する必要があり、コードの柔軟性を大幅に改善します。
クラス名に基づいて裁判官を動的に作成する必要がある場合があり、閉鎖をすばやく生成するのに役立つ関数を書くことができます。
<?php
function makeIsATypeChecker(string $className) {
return function($obj) use ($className) {
return is_a($obj, $className);
};
}
$typeCheckers['cat'] = makeIsATypeChecker('Cat');
// テスト
class Cat extends Animal {}
$cat = new Cat();
var_dump(checkType($cat, 'cat', $typeCheckers)); // bool(true)
?>
これにより、私たちのタイプジャッジシステムはより多用途でメンテナンスが容易になります。
オブジェクトが特定のインターフェイスを実装するか、特定の親クラスを継承するかを判断する必要がある場合があり、より一般的な裁判官を書くことができます。
<?php
function makeClassOrInterfaceChecker(string $name) {
return function($obj) use ($name) {
return is_a($obj, $name) || in_array($name, class_implements($obj));
};
}
interface Pet {}
class Dog extends Animal implements Pet {}
$typeCheckers['pet'] = makeClassOrInterfaceChecker('Pet');
$dog = new Dog();
var_dump(checkType($dog, 'pet', $typeCheckers)); // bool(true)
?>
このようにして、相続関係とインターフェイスの実装の両方を判断することは非常に柔軟です。
<?php
class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
interface Pet {}
class DogPet extends Dog implements Pet {}
function checkType($obj, $type, $checkers) {
if (!isset($checkers[$type])) {
throw new InvalidArgumentException("不明なタイプ: $type");
}
return $checkers[$type]($obj);
}
function makeIsATypeChecker(string $className) {
return function($obj) use ($className) {
return is_a($obj, $className);
};
}
function makeClassOrInterfaceChecker(string $name) {
return function($obj) use ($name) {
return is_a($obj, $name) || in_array($name, class_implements($obj));
};
}
$typeCheckers = [
'dog' => makeIsATypeChecker('Dog'),
'animal' => makeIsATypeChecker('Animal'),
'pet' => makeClassOrInterfaceChecker('Pet'),
'string' => function($obj) { return is_string($obj); },
];
// テスト
$dog = new Dog();
$cat = new Cat();
$dogPet = new DogPet();
var_dump(checkType($dog, 'dog', $typeCheckers)); // true
var_dump(checkType($cat, 'animal', $typeCheckers)); // true
var_dump(checkType($dogPet, 'pet', $typeCheckers)); // true
var_dump(checkType("hello", 'string', $typeCheckers));// true
?>
このようにして、さまざまな複雑なビジネスニーズのために、柔軟でスケーラブルなタイプの裁判官を簡単に構築できます。