J'ai simplifié j'avais la flemme de créer une interface Beggar qui ne me servait à rien pour mon exemple, mais bon je vais corriger :p
Ta méthode est de traviole: tu acceptes en entrée n'importe quel $object, donc ta méthode (son algorithme) doit être capable de traiter n'importe quel objet.
Si c'est un Beggar ou un Kid, elle est faite de travers car tu appelles une méthode dessus alors que le typage de $object est mixed, et le instanceof te dis juste qu'il est Beggar/Kid (pas de giveGold définit sur ces interfaces). Ton problème ici n'est pas que tu as une méthode qui discrimine, en interne, les cas; ton problème est que tu acceptes en entrée n'importe quelle variable ($object est non typé) et que tu fais ensuite des appels de méthode dessus. C'est comme si tu m'avais présenté ce code:
D'ailleurs, fait le test sur Netbeans: si le instaceof est fait, Netbeans te propose l'auto-complétion des méthodes associées à cette interface. s'il n'est pas fait, il ne te propose rien. Ce que j'essaie de te faire passer, c'est que le typehinting définit ce que la méthode accepte en entrée, alors que l'instanceof définit comment son algorithme interne traite cette entrée, et cette méthode de traitement ne doit pas transpirer hors de la classe.
J'ai en effet oublié giveGold
C'est mieux ? Tu vois le soucis que ça va avoir ?
Je croyais l'absence de giveGold volontaire (je la suppose présente dans Kid aussi). Note que si elle est définit dans chacun des interfaces, alors même si elle a la même signature, ce ne sera pas la même méthode (car pas la même interface). Si c'est censé être la même méthode (avec seulement des valeurs pour giveGold qui changent), il faut qu'elle se trouve dans une interface séparée. Après, ou bien on typehint askGold avec cette interface, ou bien on instanceof dans cette interface.
Non, quel problème est censé survenir, qui ne surviendrait pas dans ton autre méthode?
Je créer un nouveau Héro CalamityJane :
Toujours d'accord ? Pas de soucis ? Le code original sans CalamityJane était une librairie. CalamityJane est dans notre projet. On met à jour la librairie et Conan sait maintenant gérer les Femmes.
Tout joyeux dans mon code je me mets à utiliser cette nouvelle feature ou j'en ai besoin :
Et la vie est belle.Puis plusieurs mois après, j'ajoute un système qui permet à CalamityJane de rencontrer des femmes :
Et bien là, ça ne fait pas du tout ce que j'attendais.Je débug et je me rends vite compte pourquoi : j'ai oublié de rajouter l'instanceof Women dans CalamityJane. Citation :Conan sait maintenant gérer les Femmes. Tu continues à confondre ce que la méthode accepte, et ce qu'elle en fait. Conan accepte n'importe quel objet, c'est la signature de la méthode qui le dit. Donc Hero gère n'importe quel objet, Femmes incluses, et si Conan décide de donner son or aux Femmes, c'est sa décision propre, interne. L'algorithme de Conan ne discriminait pas les Femme avant, dans la nouvelle version oui. C'est la doc de Conan qui te le dit. L'objet Conan, pour le monde extérieur, n'a pas changé: il accepte toujours les mêmes messages puisque les signatures sont identiques. C'est sa façon de réagir qui a changé (comme ta TV incassable: elle acceptait encore le message "casse-toi", mais elle l'ignorait), et ça, c'est la doc qui te le définit (la doc de Conan). Dans tout code, la sémantique est importante: si c'est copié/collé, c'est deux choses indépendantes qui agissent indépendamment. CalamityJane et Conan partagent la même interface: leurs méthodes acceptent la même chose. Ils ne partagent pas la même implémentation: leur façon de traiter le message diffère. Si Conan gère les Femme, tant mieux pour lui, mais en aucun cas cela ne concerne CalamityJane: seule son interface l'intéresse. Pour bien le voir, voici l'espace publique de la lib et du projet: Code : interface Hero C'est cela qui compte. C'est ce "contre" quoi tu codes. La discrimination éventuelle faite dans chaque classe, on s'en fiche. Que Conan décide de "gérer les Femme", c'est à dire de leur envoyer de l'or, c'est la décision interne de la classe. Elle apparait dans la doc, pas dans la signature de la méthode (c'est la liberté de la méthode de faire telle ou telle action dans telle ou telle situation). Donc, non le "problème" soulevé n'en est pas un car la méthode de Hero gère n'importe quel objet, mais chaque classe implémente cette gestion comme elle l'entend. C'est le fondement d'une interface. Note: cet espace publique est très peu pollué; dans la 2nde méthode, l'espace publique, aka la liste des messages acceptés par chaque interface donc par chaque classe, explose vite. Note2 : l'algo de Conan est étrange: si un objet est Beggar&Kid&Femme, il lui file 3x son or...
05-06-2015, 12:08 PM
Donc au final comment je fais pour savoir quel objet est capable de gérer un Hero ?
Je regarde la doc c'est ça ?
05-06-2015, 12:25 PM
Le fondement d'une interface c'est de définir un contrat précis pas autre chose ^^
Oui, le fondement de l'interface, c'est de définir les messages auxquels les classes les implémentant répondent. Ce n'est nullement de définir comment l'algorithme interne de ces classes se déroule (sinon, chaque méthode de chaque classe aurait sa propre interface dédiée).
Reprends la définition de la doc PHP: "Object interfaces allow you to specifie which methods a class must implement, without having to define how these methods are handled.". Chaque classe est libre d'implémenter la méthode à sa manière, et d'appliquer sa logique propre dans cette méthode. Si tu veux savoir qui est capable de gérer un Hero, tu regardes le typehinting des méthodes : Code : interface Hero Donc, qui accepte un Hero en entrée? Hero::askGold(mixed) Beggar::meetHero(Hero) Beggar::giveGold(mixed) Kid::giveGold(mixed);. Toutes ces classes acceptent un Hero en entrée: tu leur passe un Hero, elles font un truc sans planter au niveau du langage. Quel algorithme elles utilisent pour traiter cette entrée? Ca, c'est pas donné dans la signature de la méthode, mais dans la documentation de cette méthode pour chaque classe.
05-06-2015, 02:17 PM
C'est bien ce que je pointe du doigt.
askGold mixed, en gros tu peux même passer un int, tu passes ce que tu veux, donc tu ne sais pas comment travailler avec ton object. Puisque le réel but de askGold c'est pas de marcher avec n'importe quel objet, ça aurai pu être le cas mais pas ici. |
|