Maison > Questions et réponses > le corps du texte
P粉7029469212023-09-03 20:17:24
Je ne dis pas que les interfaces "changent le comportement d'une classe", je dis que les interfaces facilitent étendre les fonctionnalités de classe.
Pour comprendre l'interface, en tant que concept de programmation orientée objet, nous devons d'abord comprendre quel problème elle veut résoudre.
Une interface est un contrat. Voici comment implémenter duck-typing en PHP. Vous devez penser du point de vue d'un rédacteur de bibliothèque qui souhaite exposer les fonctionnalités aux autres. Par exemple,
class Greeter { public function greet($person) { echo "Hello, {$person->getName()}!\n"; } }
Pour garantir que les usagers de la bibliothèque connaissent la méthode $person
需要有 getName()
方法,您可以创建一个类 Person
> 有一个 getName()
. Utilisez ensuite les déclarations de type pour détecter les erreurs potentielles lorsque le code est résolu.
class Greeter { public function greet(Person $person) { echo "Hello, {$person->getName()}!\n"; } } class Person { public string $name; public function getName(): string { return $this->name; } }
Supposons qu'il existe une autre bibliothèque qui nourrit les objets avec de la nourriture :
class Feeder { public function feed(Eater $eater, string $food) { $eater->eat($food); } } class Animal { private $stomach = []; public function eat(string $food) { $stomach = $food; } }
Maintenant, disons que l'utilisateur souhaite écrire une fonction qui peut à la fois manger et dire bonjour Pet
类。用户不想仅仅为了 Pet
Réécrivez ces fonctions.
Comment écrire Pet
以便同时使用 Greeter
和 Feeder
bibliothèque ?
Peut-être que c'est le cas ?
class Pet extends Person, Animal { }
Malheureusement, PHP ne prend pas en charge l'héritage multiple. Une classe ne peut avoir qu'une seule classe. Le code ci-dessus n'est pas valide. Ainsi, dans la situation actuelle, les utilisateurs ne peuvent utiliser qu’une seule des bibliothèques. 扩展
. getName() 返回
$first_name
和 $last_name
代码>)。您的库类中可能没有合理的默认实现 getName()
Comment résoudre ce problème en utilisant les "interfaces" en PHP ?
À l'aide des interfaces, vous pouvez réécrire les deux bibliothèques comme ceci :
Greeter
class Greeter { public function greet(Namer $namer) { echo "Hello, {$namer->getName()}!\n"; } } interface Namer { public function getName(): string; }
Feeder
class Feeder { public function feed(Eater $eater, string $food) { $eater->eat($food); } } interface Eater { public function eat(string $food); }
classe suivante est donc tout à fait valide en PHP : Pet
class Pet implements Namer, Eater { private array $stomach = []; private string $name = ''; public function __construct(string $name) { $this->name = $name; } /** * Implements Namer. */ public function getName(): string { return $this->name; } /** * Implements Eater. */ public function eat(string $food) { $this->stomach[] = $food; } } $greeter = new Greeter(); $feeder = new Feeder(); $pet = new Pet('Paul'); $greeter->greet($pet); $feeder->feed($pet, 'a biscuit');Maintenant, les objets de cette
classe peuvent être utilisés avec la bibliothèque Pet
类的对象可以与 Greeter
库和 Feeder
et la bibliothèque
ArrayAccess
Un peu comme les interfaces que nous avons mentionnées précédemment, PHP fournit des fonctionnalités aux classes qui l'implémentent. Mais au lieu de fournir l'Greeter
或 Feeder
exemple ci-dessus, le noyau PHP fournit sucre syntaxique pour une classe qui implémente ArrayAccess. Cela signifie que vous pouvez utiliser un code plus simple lorsque vous traitez avec des classes qui implémentent l'interface AccessAccess.
Dans l'exemple officiel,
<?php class Obj implements ArrayAccess { private $container = array(); public function __construct() { $this->container = array( "one" => 1, "two" => 2, "three" => 3, ); } public function offsetSet($offset, $value) { if (is_null($offset)) { $this->container[] = $value; } else { $this->container[$offset] = $value; } } public function offsetExists($offset) { return isset($this->container[$offset]); } public function offsetUnset($offset) { unset($this->container[$offset]); } public function offsetGet($offset) { return isset($this->container[$offset]) ? $this->container[$offset] : null; } }
Si vous les avez implémentés, remplacez-les par :
$obj = new Obj; $obj->offsetSet(10, "hello"); $obj->offsetSet(11, "world"); if ($obj->offsetUnset(12)) { $obj->offsetUnset(12); } echo $obj->offsetGet(11);
Vous pouvez utiliser $obj
avec une syntaxe de type tableau pour rendre votre code plus court :
$obj = new Obj; $obj[10] = "hello"; $obj[11] = "world"; if (isset($obj[12])) { unset($obj[12]); } echo $obj[11];