Dans PHP, la fonction IS_A est utilisée pour déterminer si un objet est une instance d'une classe ou de sa sous-classe. Il est très adapté à la détection de type. Mais si vous souhaitez rédiger un juge de type plus flexible et extensible, vous pouvez combiner des fermetures (fonctions anonymes) pour implémenter la logique de jugement dynamique, évitant ainsi d'écrire un tas de relevés en double si ou de commutation .
Jetons un aperçu étape par étape sur la façon d'écrire un juge de type flexible en utilisant la fonction IS_A combinée à la fermeture.
<?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 peut déterminer si un objet est une instance d'une certaine classe ou de sa sous-classe, qui nous fournit la base de juger le type.
Nous pouvons utiliser des fermetures pour définir différentes règles de jugement, puis les appeler avec une interface unifiée.
<?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);
}
];
// Exemple d'utilisation
function checkType($obj, $type, $checkers) {
if (!isset($checkers[$type])) {
throw new InvalidArgumentException("Type inconnu: $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)
?>
De cette façon, l'ajout d'un nouveau jugement de type nécessite seulement d'ajouter une fermeture au tableau $ typeCheckers , améliorant considérablement la flexibilité du code.
Parfois, nous devons créer dynamiquement un juge basé sur le nom de la classe, et nous pouvons écrire une fonction pour nous aider à générer rapidement des fermetures:
<?php
function makeIsATypeChecker(string $className) {
return function($obj) use ($className) {
return is_a($obj, $className);
};
}
$typeCheckers['cat'] = makeIsATypeChecker('Cat');
// test
class Cat extends Animal {}
$cat = new Cat();
var_dump(checkType($cat, 'cat', $typeCheckers)); // bool(true)
?>
Cela rend notre système de juge de type plus polyvalent et facile à entretenir.
Parfois, nous devons déterminer si l'objet implémente une certaine interface ou hérite d'une certaine classe parent, et nous pouvons écrire un juge plus général:
<?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)
?>
De cette façon, il est très flexible de juger à la fois la relation d'héritage et la mise en œuvre de l'interface.
<?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 inconnu: $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); },
];
// test
$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
?>
De cette façon, vous pouvez facilement construire un juge de type flexible et évolutif pour une variété de besoins commerciaux complexes.