Debuts en POO - Apprendre-PHP.com

Rechercher
PHP5 Avancé - Eric Daspet et Cyril Pierre de Geyer - Commander sur Amazon.fr

Debuts en POO

Par paintbox -  21 reponses -  Le 29/08/2011 -  Flux RSS - 

Hello Cyrano,

 

je tente de me mettre à la programmation orientée objet mais je butte déjà sur un premier exercice.

J'ai pourtant suivi les tutoriaux de ApprendrePhp. 

Je créé un class person dont les attribnuts sont nom, prenom et adresse.

Je créé une fonction pour afficher les infos et une autre qui permet de modifier l'adresse.

Malheureusement, rien ne s'affiche et je ne vois pas où il y aurait une erreur.

Voici le code : 

class Person
{
private $nom;
private $prenom;
private $adresse;
 
// => Constructeur
public function _construct($nom, $prenom, $adresse)
{
$this->nom = $nom;
$this->prenom = $prenom;
$this->adresse = $adresse;
}
 
// => Affichage des données
public function getInfo()
{
$coord = "$this->nom $this->prenom $this->adresse";
return $coord;
}
 
// => Modification de adresse
public function setAdresse($adresse)
{
$this->adresse = $adresse;
}
}
 
// Creation d'objets
$person1 = new Person("Albert", "Marc", "46 Avenue du Parc");
 
echo $person1->getInfo();

 

 

 

Réponses apportées à cette discussion

Par Cyrano -  Le 29/08/2011 - 

Salut,

j'ai eu un peu de mal à le voir, ce n'est pas évident comme erreur : il s'agit de la différence entre _ et __ pour nommer ton constructeur.

Là tu as écrit _construct au lieu de __construct, donc syntaxiquement il n'y a pas d'erreur, mais ce n'est qu'une méthode ordinaire comme les autres et non le constructeur, donc les éléments qui sont envoyés lors de la création de l'instance ne servent jamais parce que le constructeur est dans ce cas implicite et ne comporte aucun paramètre, ceux qui sont envoyés ne servant à rien. En rajoutant un simple « _ » à ton constructeur, ça va résoudre ton soucis ;)

 

 
Par paintbox -  Le 29/08/2011 - 

Hello Cyrano,

 bien vu!  Je crois que j'aurais encore pu chercher longtemps. Je ne pensais pas dutout à ce type d'erreur. Cela fonctionne effectivement mieux. J'avais également remarqué qu'aucun paramètre ne passait.

Comme je le disais, je commence la POO et même si je comprends le principe, le fonctionnement… j'ai du mal a voir cela en pratique. Donc si tu as  des exemples d'utilisations ou des sites avec des exercices…, je suis preneur (je sais que t'es explications sont très bonnes et m'ont bien servies jusqu'à présent)

 

Encore merci ! 

 

 
Par Cyrano -  Le 30/08/2011 - 

Il y aurait un très bon bouquin pour comprendre les concepts de l'orienté-objet, malheureusement l'éditeur n'existe plus en France, il faudrait donc tenter de le trouver en occasion : « Analyse et conception orientée objet - tête la première » publié chez O'Reilly, sinon il est aussi disponible au format numérique à la Fnac

J'avais eu un peu de mal à rentrer dedans au départ parce qu'il est surtout basé sur la programmation en Java qui pour le coup est un langage full objet. Mais les principes sont les mêmes en PHP.

Sinon, dis-toi que certains principes de bases sont indispensables : par exemple, une classe ne fait qu'une seule chose, mais elle le fait bien. Et pour certains traitements complexes, on aura parfois besoin de combiner plusieurs classes. Le plus diffcile en débutant consiste à identifier ce qui peut être considéré ou non comme un objet. C'est souvent assez abstrait. On se pose aussi souvent la question de l'intéret de la POO par rapport à des collection de fonctions qu'on pourrait inclure comme on le fiait en procédural. Ce point est du reste de mon point de vue difficile à expliquer, ça vient avec l'usage et en fin de compte, ça simpifie la vie. Mais je dirais aussi surtout que ça amène à utiliser des principes de programmation propres et durables dans le temps. On crée des classes qui sont portables sur de très nombreux projets. À terme, ça a amené à la création d'ensembles beaucoup plus complexes comme Symfony, Zend Framework et autres du genre qui font que lorsqu'on construit une application, on peut se concentrer sur le code métier au lieu de devoir aussi écrire certains traitements qui existent déjà ailleurs et qu'on pourrait reprendre sans modification.

Petit à petit, tu vas réaliser qu'il n'est pas inutile d'avoir une vision d'ensemble des paquets de classes et que la modélisation peut simplifier beaucoup la conception : ça devrait t'inciter à t'intéresser à la modélisation en UML.

 

 
Par paintbox -  Le 30/08/2011 - 

Hello,

 

merci pour ces conseils. Effectivement j'essai aussi de me mettre à l'ULM. Je vais essayer de trouver le livre dont tu parles.

Et pour la POO je crois, comme tu le dis, que cela viendra à force d'en faire. C'est donc mon nouvel objectif.

Encore merci 

 
Par paintbox -  Le 31/08/2011 - 

Hello Cyrano,

nouveau soucis dans mon apprentissage de l'orienté objet.

Je suis en train de faire un tuto trouvé sur un site.

L exercice est la gestion des commandes d'une pizzeria.

 

Voici ma class :

  1. class Commande
  2. {
  3. public $nomClient;
  4. public $listePizza = Array();
  5.  
  6. public $prixRoyal = 6;
  7. public $prixCampagnarde = 8;
  8.  
  9. // Ajout quantité pizza royale
  10. public function ajouterRoyale($nombre)
  11. {
  12. $this->listePizza[0]+=$nombre;
  13. }
  14.  
  15. // Ajout quantité pizza campagnarde
  16. public function ajouterCampagnarde($nombre)
  17. {
  18. $this->listePizza[1]+=$nombre;
  19. }
  20.  
  21.  
  22. // Fonction qui calcul le prix
  23. public function calculerPrix()
  24. {
  25. $montant_Royal = $this->listePizza[0] * $this->prixRoyal;
  26. $montant_Campagnarde = $this->listePizza[1] * $this->prixCampagnarde;
  27.  
  28. return $montant_Royal + $montant_Campagnarde;
  29. }
  30.  
  31. // Fonction qui affiche le resultat de la commande
  32. public function afficherCommande()
  33. {
  34. echo 'Commande du client : '.$this->nomClient;
  35. echo '<br />Pizza(s) Royale : '.$this->listePizza[0];
  36. echo '<br />Pizza(s) Campagnarde : '.$this->listePizza[1];
  37. echo '<br />Total de votre commande : '.$this->calculerPrix();
  38. echo ' Euros<br />';
  39. }
  40.  
  41. }

 

Ensuite, voici la page sur laquelle je créé mes objets et ou j'indique la quantité de pizza commandées

 

  1. include ('pizza.class.php');
  2.  
  3. $client = new commande();
  4. $client->nomClient="Dupont";
  5.  
  6. $client->listePizza[0]=5;
  7. $client->listePizza[1]=2;
  8.  
  9. echo 'Nom du client 1 : '.$client->nomClient.'<br />';
  10. echo 'Quantite de Pizza Royale commandee : '.$client->listePizza[0].'<br /><br />';
  11. $client->afficherCommande();
  12.  
  13. $client2 = new Commande();
  14. $client2->nomClient='Durand';
  15. $client2->ajouterCampagnarde(12);
  16.  
  17.  
  18. echo 'Nom du client 2 : '.$client2->nomClient.'<br />';
  19. echo 'Quantite de Pizza Campagnarde commandee : '.$client2->listePizza[0].'<br /><br />';
  20. $client2->afficherCommande();

 

 

Pour info, listePizza correspond aux différentes pizzas. C'est un tableau qui contient pour l'instant 2 pizzas.

En fait j'obtiens à plusieurs reprises des Undefined Offset.

 

Je ne comprends pas pourquoi. J'ai tenté de déclarer listePizza en array mais cela ne change rien.

J'ai fais un var_dump de listePizza et le résulat me parrait correct.

 

J'aurais donc besoin de tes lumières pour m'éclairer sur ce problème.

 

Merci 

 

 
Par paintbox -  Le 31/08/2011 - 

J'ai compris mon erreur.

 

En fait dans mes fonctions ajouterRoyale et ajouterCampagnarde, je faisais un $this->listePizza[0]+=$nombre; alors que je n'avais pas initialisé  $listePizza.

en déclarant ceci public $listePizza = Array("0", "0"); ou en testant si  $listePizza est vide, mon problème est résolu.

 

Merci 

 
Par Cyrano -  Le 31/08/2011 - 

Presque.

Là j'ai pas trop le temps mais ce soir je te ferai quelques commentaires sur tes classses. Tu es bien parti, maintenant on va optimiser un peu tout ça en introduisant quelques concepts techniques qui, une fois mis au jour, vont te sembler évidents quant à l'optimisation générale.

À plus tard ;) 

 
Par paintbox -  Le 31/08/2011 - 

Ok j attends tes explications !

Merci 

 
Par Cyrano -  Le 31/08/2011 - 

Salut,

en fait j'ai réalisé que c'était bon. À ce stade, ce ne serait peut-être pas une bonne idée de commencer à te noyer dans des concepts tordus. Donc tel que c'est avec ta correction sur la déclarration de ta propriété de classe $listePizza, c'est très bienn.

 

Juste un truc quand même : évite autant que possible d'utiliser un echo() dans une classe. Une classe est faire pour manipuler des données et retourner ou non des valeurs à partir de ces données, il faut déléguer l'affichage à une autre partie. Tu pourrais avoir cependant une utilisation intéressante de la méthode magique __toString() : remplace ta méthode afficherCommande par ceci :

  1. /**
  2.   * Affichage de l'instance de la classe dans son état courant.
  3.   *
  4.   * @return String
  5.   */
  6. public function __toString()
  7. {
  8. $affichage = 'Commande du client : '.$this->nomClient .
  9. '<br />Pizza(s) Royale : '.$this->listePizza[0] .
  10. '<br />Pizza(s) Campagnarde : '.$this->listePizza[1] .
  11. '<br />Total de votre commande : '.$this->calculerPrix() .
  12. ' Euros<br />';
  13. return $affichage;
  14. }

Ensuite, au lieu de faire « $client2->afficherCommande(); », fais un « echo($client2); » et... découvre pourquoi on appelle ça une méthode magique ;)

 

 

 
Par paintbox -  Le 31/08/2011 - 

Hello Cyrano,

concernant le echo dans la classe, oui en effet j'avais aussi lu que c'était déconseillé, mais le tutos que j'ai trouvé procédait comme cela. Pas toujours évident d'avoir une bonne méthode quand on se base sur divers tutos péchés à gauche à droite.  En tout cas je note que ce n'est plus à refaire!

 Concernant  la méthode magique… hum je ne vois pas trop.

En cherchant sur le net, j'ai trouvé ceci :

"La méthode __toString détermine comment la classe doit réagir lorsqu'elle est convertie en chaîne de caractères.

Mais j'avoue que je ne vois pas  de différence entre mon affichage et celui avec __toString(), ou alors quelque chose m'échappe sans doute.

 

Je vais essayer de traiter un formulaire de contact (methode POST) à l'aide de la POO, mais je suis un peu perdu. J'ai une vague idée que je vais appliquer.

 

Merci pour tes explications !

 

 

 

 
Par Cyrano -  Le 31/08/2011 - 

La raison est simple : il n'y a plus de echo dans la classe elle même et tu gères l'affichage à l'extérieur, c'est pas plus compliqué que ça ;)

 
Par paintbox -  Le 31/08/2011 - 

Ok, je voulais sans doute chercher trop loin. Et en effet je viens de tester :

 

  1. public function afficherCommande()
  2. {
  3. $affichage = 'Commande du client : '.$this->nomClient .
  4. '<br />Pizza(s) Royale : '.$this->listePizza[0] .
  5. '<br />Pizza(s) Campagnarde : '.$this->listePizza[1] .
  6. '<br />Total de votre commande : '.$this->calculerPrix() .
  7. ' Euros<br />';
  8. return $affichage;
  9. }

 

et cela ne me retourne pas le même résultat qu'avec __toString()

 

Je viens de tester le formulaire. C'est basique dans un premier temps mais puis-je te demander ton avis sur la façon de faire? Est-ce la bonne méthode, il y a t-il mieux ?

 

Voici ma classe :

  1. class monForm
  2. {
  3. private $nom;
  4. private $prenom;
  5.  
  6. public function __construct($nom, $prenom)
  7. {
  8. $this->nom = $nom;
  9. $this->prenom = $prenom;
  10. }
  11.  
  12. public function __toString()
  13. {
  14. $message = "Bonjour " .$this->nom.' , '.$this->prenom;
  15. return $message;
  16. }
  17. }

 

Et ma page avec mon formulaire :  

  1. <?php
  2. include_once('monForm.class.php');
  3. ?>
  4. <html>
  5. <body>
  6. <?php
  7.  
  8. if (isset($_POST['envoyer']))
  9. {
  10. $client = new monForm($_POST['nom'], $_POST['prenom']);
  11.  
  12. echo $client;
  13. }
  14. else
  15. {
  16. ?>
  17. <form method="post" action="" name="monformulaire">
  18. <label>Nom : </label>
  19. <input type="text" name="nom" />
  20.  
  21. <label>Prenom : </label>
  22. <input type="text" name="prenom" />
  23.  
  24. <input type="submit" name="envoyer" value="Envoyer" />
  25. </form>
  26. <?php
  27. }
  28. ?>
  29. </body>
  30. </html>

 

Suis-je dans le bon? Est-ce que je fais bon usage de la POO de cette façon?

 

Merci pour ton avis 

 
Par Cyrano -  Le 31/08/2011 - 

DIsons que pour le moment, j'ai l'impression que tu es en phase d'exploration et la POO est un vaste domaine. L'important est d'obtenir le résultat voulu dans un premier temps.

Dans un second temps, l'idée des classe est de créer des systèmes de traitement génériques et réutilisables dans à peu près n'importe quelle application. C'est comme ça qu'on commence en général rapidement par se construire des classes pour l'accès aux bases de données, puis des classes de traitements de données par exemple pour valider des informations en provenance d'un formulaire, ou encore des classes qui permettent d'envoyer des courriels plus facilement qu'avec les simples méthodes natives du langage qui obligeraient à écrire plus de code.

Plus tard, on intègre les « Design Pattern » ou « Motifs de conception » qui sont des solution génériques à des problèmes récurrents  dans la manière d'organiser les différentes classes entre elles.

Je ne sais pas si tu as fait une recherche du bouquin que je t'ai suggéré plus tôt, mais ce ne sera pas une perte de temps, d'autant moins si tu le trouve, et ce ne sera pas de l'argent jeté par les fenêtres si tu l'achètes, c'est une petite mine d'or qui te fera gagner bien du temps dans la compréhensions générale et dans certains cas bien particuliers de la POO. Autre bouquin pour aborder la POO en PHP5, c'est « PHP5 Avancé » de Cyril Pierre de Geyer et publié chez Eyrolles, le chapitre sur la POO est assez complet même si les exemples sont assez basiques, mais tu y verras tous les aspects fondamentaux et essentiels. Celui-ci est en revanche toujours disponible en librairie, il en est à la 5ième édition ce me semble.

 
Par paintbox -  Le 02/09/2011 - 

Hello Cyrano,

 

en effet je suis encore en phase d'exploration. Je teste et j'essaie de voir l'usage que je peu faire de la POO. Comme je l'ai dit, je comprend le principe et le fonctionnement mais j'ai du mal à voir la POO en pratique, de "visualiser" des cas pratiques. Je cherche des exercices sur le net mais pas évident d'en trouver.

 Le premier libvre que tu m'as recommandé a l'air effectivement très bien. Malheureusement comme tu le craignais, il est épuisé sous format papier. Je vais encore voir si je n'arrive pas à en dénicher un, je voudrais éviter le format PDF moins agréable à consulter. 

Merci 

A+

 

 

 
Par paintbox -  Le 02/09/2011 - 

Hello Cyrano,

j'aurais besoin une fois de plus de tes coseils sur la bonne façon d 'utiliser "l'héritage". Je suis toujours dans la phase apprentissage et tests. Je test l'héritage.

Voici mon problème j'ai créé une class parent  "animaux" dont les attributs sont $nbpates et $nbyeux.

J'ai 2 autres classes enfants "chat" et "chien".

Mon soucis est que j'ai eu du mal a définir les attributs "parent" et "enfants".

Pour info, j'avais d'abord créé un constructeur pour la classe parent ($nbpates et $nbyeux) et un constructeur pour la class chat pour l'attribut $crichat. Je n'arrivais pas à attribuer des valeurs aux différents attributs de chacun. J'ai donc créé un seul constructeur pour chat qui attribue les 3 attributs.

Je voudrais tes conseils sur la bonne manière de faire.

 

Voici mon code :

  1. class animaux
  2. {
  3. // Declaration des attributs
  4. public $nbpates;
  5. public $nbyeux;
  6.  
  7. // Constructeur
  8. //public function __construct($nbpates, $nbyeux)
  9. // {
  10. // $this->nbpates = $nbpates;
  11. // $this->nbyeux = $nbyeux;
  12. // }
  13. }

 

 

Mes class chat et chien : 

  1. class chat extends animaux
  2. {
  3. // Declaration des attributs
  4. private $crichat;
  5.  
  6. // Constructeur
  7. public function __construct($nbpates, $nbyeux, $crichat)
  8. {
  9. $this->nbpates = $nbpates;
  10. $this->nbyeux = $nbyeux;
  11. $this->crichat = $crichat;
  12. }
  13. }

 

 

  1. class chien extends animaux
  2. {
  3. // Declaration des attributs
  4. private $crichien;
  5. }

 

  Merci

 

 
Par Cyrano -  Le 02/09/2011 - 

Ok, alors en résumé, le principe de déclinaisons de classes héritant les unes des autres consisteà partir du plus générique vers le plus spécifique. Comme tu l'as compris, et comme tes classes le reflêtent bien, les animaux ont des points communs et des points quileurs sont propres. Il faut donc arriver à déterminer ce qui est réellement générique du reste et voir éventuellement ce qui est commun dans leurs spécificités.

Lorsqu'on crée ce genre de montage, on va souvent utiliser une « Super-classe » parente et une interface où on va définir les méthodes des classes qui héritent de la super-classe. En arrière-plan, tu verras peut-être apparaître l'idée de polymorphisme. Lorsque tu crée un objet, il a un certain type, mais lequel : celui de la classe héritant ou de la super-classe ? Les deux, mais pour  des questions de bonnes pratique, on se basera sur le type de la super-classe. On pourra alors utiliser les mêmes méthodes que l'objet soit « chien » ou « chat »

Mais lorsque tu définis les propriétés d'un chien ou d'un chat, ta manière de faire ici n'apporte pas grand chose : tu es obligé de préciser lorsque tu crée ton instance les valeurs de ces propriétés : du coup, tu n'as en réalité plus besoin des sous-classes. Pour corriger le tir, dans la mesure ou tes sous-classes sont déjà spécialisées, tu peux pré-définir les valeurs de ces propriétés dans les sous-classes elle-mêmes. Ce qui par contre changera, c'est surtout au niveau des méthodes dans leur implémentation. Les méthodes seront les mêmes pour toutes les sous-classes, mais l'implémentation dépendra de la sous-classe spécifique.

Revoyons tes classes et voyons comment les exploiter :

  1. <?php
  2. abstract class animaux
  3. {
  4. protected $animal;
  5. protected $nbpates;
  6. protected $nbyeux;
  7. protected $cri;
  8.  
  9. public function jesuis()
  10. {
  11. return "Je suis ". $this->animal;
  12. }
  13. }
  14.  
  15. class chat extends animaux
  16. {
  17. public function __construct()
  18. {
  19. $this->animal = 'un chat';
  20. $this->nbpates = 4;
  21. $this->nbyeux = 4;
  22. $this->cri = 'Miaou !';
  23. }
  24. }
  25.  
  26. class chien extends animaux
  27. {
  28. public function __construct()
  29. {
  30. $this->animal = 'un chien';
  31. $this->nbpates = 4;
  32. $this->nbyeux = 4;
  33. $this->cri = 'Wouaff !';
  34. }
  35. }
  36.  
  37. class mouche extends animaux
  38. {
  39. public function __construct()
  40. {
  41. $this->animal = 'une mouche';
  42. $this->nbpates = 6;
  43. $this->nbyeux = 2;
  44. $this->cri = 'Bzzzz !';
  45. }
  46. }

Première observation : on ne crée jamais directement d'instance de la classe animaux : on va donc la déclarer abstraite. Les propriétés et méthodes qui s'y trouveront seront le plus souvent protégées et devront être redéfinies dans les sous-classes.

Lorsque je crée un objet chien, je n'ai nul besoin de préciser les valeurs de ses propriétés, c'est directement dans le constructeur spécifique. Ce qui nous intéresse par contre, c'est d'avoir des méthodes pour récupérer les valeurs de ces propriétés.J'ai donc mis une méthode publique jesuis() qui retourne l'identité de l'animal, identité que je définis dans le construteur de la sous-classe.

Pour être sur que toutes mes classes ont bien les mêmes méthodes, en marges des méthodes publiques directement héritées de la super-classe et les implémentent, on a deux possibilités:

  1. ajouter une interface qu'implémenteront toutes les sous-classes. 
  2. Créer des méthodes protégées dans la super-classes qui devront être redéfinies dans les sous-classes.

On va prendre la seconde solution, 

Ajoutons une méthode crier dans la super-classe, mais cette fois on mettra une méthode protégée.

  1. abstract class animaux
  2. {
  3. protected $animal;
  4. protected $nbpates;
  5. protected $nbyeux;
  6. protected $cri;
  7.  
  8. public function jesuis()
  9. {
  10. return "Je suis ". $this->animal;
  11. }
  12.  
  13. abstract protected function crier();
  14. }

Maintenant, jouons un peu avec nos objets :

  1. $oChien = new chien();
  2. $oChat = new chat();
  3. $oMouche = new mouche();
  4.  
  5. echo("<p>". $oChien->jesuis() ."</p>\n"); // Affiche : Je suis un chien
  6. echo("<p>". $oChat->jesuis() ."</p>\n"); // Affiche : Je suis un chat
  7. echo("<p>". $oMouche->jesuis() ."</p>\n"); // Affiche : Je suis une mouche

Jusque là, tout va bien. Si maintenant il me prenait la fantaisie d'appeler la méthode crier, j'aurais un problème :

  1. echo("<p>". $oChien->crier() ."</p>\n");

Le résultat est simple :

  1. Fatal error: Class chat contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (animaux::crier) in D:\www\_Temporaire\_tmp\PaintBox\heritage.php on line 31

Normal, ma méthode est protégée et surtout abstraite, donc accessible seulement dans la classe où elle est définie ou dans les classes héritées. Comme elle est abstraite, on doit impérativement implémenter les comportements spécifiques dans les sous-classes. Note que la méthode abstraite n'a pas de corps, donc pas de « {} », expérimente et ajoute des acoolades et exécute le code, tu vas voir ce que ça donne. Modifions la classe chien :

  1. class chien extends animaux
  2. {
  3. public function __construct()
  4. {
  5. $this->animal = 'un chien';
  6. $this->nbpates = 4;
  7. $this->nbyeux = 4;
  8. $this->cri = 'Wouaff !';
  9. }
  10. public function crier()
  11. {
  12. return($this->jesuis() ." : ". $this->cri);
  13. }
  14. }
  15.  
  16. // Appelons maintenant la méthode crier :
  17. echo("<p>". $oChien->crier() ."</p>\n"); // Affiche : Je suis un chien : Wouaff !

Voilà, ça va te donner de quoi méditer un moment avec ces éléments. Essaye de bien discerner et regarde la documentation sur les interfaces, tu vas peut-être découvrir qu'il serait plus intéressant dans le cas présent d'ajouter une interface et pourquoi ;)

 

 

 

 
Par paintbox -  Le 02/09/2011 - 

 

Ok, je comprends mieux comme ceci. Mais je crois que je commence un peu a saturer niveau POO.

J'ai compris tes explications, mis à part 2 choses : 

 

1° Je ne saisi pas trop pourquoi déclarer une méthode abstract dans animaux alors qu'on va devoir de toute façon la redéclarer dans chat, chien et mouche. On est obligé de le faire dans les 3 puisque elle est en abstract dans animaux.

 

2° si je souhaite ajouter un attribut à la class chat mais que la valeur de cet attribut dépendera de ce que l'utilisateur entrera. Exemple bidon : si je déclare un attribut $couleur qui sera vide dans ma class chat  et que je demande à l'utilisateur la couleur du chat.

La solution à laquelle je pense, est de passer en paramètre la couleur au constructeur dans la class chat. 

comme ceci:

 

  1. class chat extends animaux
  2. {
  3. public $couleur;
  4.  
  5. public function __construct($couleur)
  6. {
  7. $this->animal = 'un chat';
  8. $this->nbpates = 4;
  9. $this->nbyeux = 4;
  10. $this->cri = 'Miaou !';
  11. $this->couleur = $couleur;
  12. }
  13.  
  14. public function crier()
  15. {
  16. return($this->jesuis() ." : ". $this->cri);
  17. }
  18.  
  19. public function couleur()
  20. {
  21.  
  22. return ( $this->animal.' est de couleur '.$this->couleur);
  23. }
  24. }

 

 

Cela fonctionne, mais est-ce la bonne méthode et est-ce propre ? 

En fait si j'inciste sur le fait d'avoir un attribut dont la valeur est définie par l'utilisateur c'est dans le cas dans formulaire.

Si on a un formulaire contact identique pour  les particulier et les entreprises, on pourrait donc avoir une Super-Classe Client avec les attributs $nom, $adresse… puis avoir une Sous-Classe  Particulier  et une autre  Entreprise avec chacune des attributs propres.  Je viens de faire des recherches sur les interfaces. J'ai trouvé l'interface Iterator.  Je laisse cela pour l'instant de côté mais je compte bien y revenir ;-)

 

 
Par Cyrano -  Le 02/09/2011 - 

Ok je vois :

Une méthode abstraite présente un avantage, à première vue une entrave mais c'est loin d'être le cas, en obligeant à redéfinir la méthode dans la sous-classe. C'est pour le coup une bonne pratique qui prend tout son sens lorsqu'on travaille à plusieurs. Si un des développeur de l'équipe doit développer la classe poissonrouge, il devra obligatoirement définir une implémentation à cette méthode en retournant par exemple « Je n'ai pas de cri, je suis dans l'eau bande de neuneus ! » et personne n'aura une erreur fatale à cause d'une méthode pas définie du tout. C'est une forme de programmation par contrat : une des clause du contrat est « Tu dois implémenter cette méthode ». C'est aussi pour une question d'homogénéité globale du code.

Ajouter un attribut propre à une seule classe : rien ne l'interdit, mais dans ce cas, il sera préférable de passer par une méthode setAttribut($attr, $valeur) et alimenter une propriété qui sera par exemple un tableau. Rien n'indique que tu ne devra pas un jour développer une nouvelle sous-classe qui nécessitera également cette fonctionnalité : donc il vaut mieux anticiper, et définir la manière de rajouter des éléments de façon homogène.Pour bien faire il faudrait que je te recopie deux ou trois des chapitres du bouquin mentionné plus tôt parce que ce serait encore plus clair et basé sur des exemples homogènes.

L'idée client /particulier/entreprise à la base n'est pas une mauvaise idée, pourtant à l'usage tu réaliseras que c'est pourtant moins heureux comme solution parce que tu ne discute pas avec une entreprise mais avec son représentant qui est ... un particulier, et en fin de compte une entreprise est composée de 1 à n particuliers, et je dirais que c'est un problème que j'ai eu à me poser puisque je patauge précisément là-dedans depuis pas mal de temps : je suis sur la construction d'un outil qui doit justement traiter des problèmes du genre avec des clients qui peuvent être soit des particuliers soit des entreprises.

Mais pourtant je n'ai développé aucune classe client ni aucune classe entreprise dans mon code métier. Attention quand même à un point : PHP n'est pas Java ou C++, ce n'est pas un langage Full Objet et ce n'est pas forcément une bonne idée de vouloir tout faire un objet même si ce serait relativement faisable. Les classes que j'ai du développer par contre et dans lesquelles j'ai du mettre en pratique un certain nombre de ces concepts, c'est pas exemple mon système de gestion de formulaires ou encore mon système d'accès aux bases de données, packages complexes dans leur construction, mais qui me simplifient à l'extrème la gestion des formulaires ou de la manipulation de données dans mon code métier en limitant à assez peu de méthodes à connaître.

Et il faut distinguer ce qui est librairies de ce qui est code métier. Les librairies, ce sont des classes ou du code qui sont suffisamment génériques pour pouvoir être utilisés dans n'importe quelle application sans qu'on doive en changer une virgule, alors que le code métier, c'est le code spécifique à une application donnée parce qu'elle traite des problèmes qui lui sont propres. L'application peu être un blog, un outil de gestion de factures, un forum, un site d'agence immobilière et que sais-je encore. Tous sont différent, mais tous peuvent s'appuyer sur certaines librairies qui sont strictement identiques.

C'est là que la POO est intressante, bien pratiquée, elle homogénéise la manière de traiter des problèmes récurrents qu'on peut retrouver sous différentes formes. Et le grand art dans la conception objet, c'est que si le développement est générique et extensible, tu peux devoir étendre certaines classes trop génériques pour spécialiser davantage certains traitements pour tes besoins métier. Ainsi, je me suis écrit une classe qui étend Zend_Pdf parce que j'avais besoin de créer des documents d'une certaine manière : je ne me suis pas pris la tête à ré-écrire la classe Zend_Pdf, elle fait très bien ce qu'elle m'apportait, mais trop généraliste pour mon besoin, je l'ai simplement étendue en faisant hériter ma propre classe de Zend_Pdf.

Est-ce que ça répond à tes interrogations ?

 
Par paintbox -  Le 02/09/2011 - 

Oui c'est déjà plus claire. Je crois que j'essaie d'adapter la POO à tous les cas ce qui visiblement n'est pas toujour nécessaire. Je dois arriver à identifier les situations pour lesquelles c'est nécessaire.

Je crois que cela viendra avec la pratique.  

 Je  mets cela un peu de côté et vais m'y remettre d'ici peu.

Merci encore pour tes excellentes  explications ! 

 

 
Par  -  Le 07/01/2012 - 

mean I just read through the entire article of yours and it was quite good but since I'm more of a visual learner,I found that to be more helpful. discount uggs

 

 
Par  -  Le 07/01/2012 - 

it is very useful and wonderful post , remember !!!!! ugg boots cheap

 

 

Ajouter une réponse à la discussion

Seuls les membres loggués sont autorisés à poster dans les forums !