.. ================================================== .. FOR YOUR INFORMATION .. -------------------------------------------------- .. -*- coding: utf-8 -*- with BOM. ========================================== :abbr:`POO (Programmation Orienté Objet)` ========================================== **Théorie POO** =============== Classe et objet --------------- Une classe est une structure permettant de définir les attributs et méthodes qu’un objet peut contenir. C’est une sorte de moule qui propose des propriétés et des fonctionnalités pour tous les objets qui seront créés à partir de celle-ci. Exemple J’ai envie d’une nouvelle voiture. J’utilise le moule « Voiture ». Ce dernier propose de choisir la couleur, ainsi que le nombre de portes. Je choisis d’avoir une voiture verte à 5 portes. De plus, ma voiture pourra démarrer, s’arrêter, allumer et éteindre ses phares! Ici, les attributs sont : la couleur et le nombre de portes. Les méthodes sont : démarrer, s’arrêter, allumer et éteindre ses phares. .. code-block:: php class Car { // Attributs private $color; private $doorNumber; /** * Start a car */ public function start() { // TODO : create code } /** * Stop a car */ public function stop() { // TODO : create code } /** * Turn on or turn off headlights for a car * @param $toogle boolean Turn on or turn off headlights */ public function toggleHeadlights($toogle) { // TODO : create code } } Concrètement, que dois-je coder pour obtenir une classe (une sorte de moule) ? Et maintenant que j’ai implémenté une classe, comment puis-je obtenir ma nouvelle voiture ? .. code-block:: php $porsche = new Car(); C’est quoi ce new ? ------------------- Pour créer un nouvel objet ou une nouvelle voiture, un mot-clé est utilisé : new + le nom de la classe. En programmation, on parle d’instancier un nouvel objet. new a également une autre fonctionnalité, il appelle le constructeur de la classe. Un constructeur ? ----------------- Au départ, une classe est codée. Elle permet d’instancier plein d’objets. Mais naturellement, ce mécanisme ne se fait pas par magie. Comme dans la réalité, si on désire une nouvelle voiture, il faut un jour ou l’autre, mettre les mains dans le cambouis pour que la voiture finissent par ronronner. C’est pareil pour un objet, il sera fonctionnel qu’une fois « construit ». Le new va permettre de construire l’objet (donc, de l’instancier). Concrètement, il va appeler une méthode particulière qui effectue les premiers réglages et alloue la place mémoire nécessaire à l’objet. Cette méthode est appelé constructeur de la classe. En PHP, elle s’appelle__construct(). Le constructeur peut avoir des paramètres. Dans certains langages, il est possible d’avoir plusieurs constructeurs définis par des paramètres différents. En PHP, il y a un constructeur de classe.  Voici le code du constructeur pour cette classe : .. code-block:: php class Car { // Attributs protected $color; protected $doorNumber; /** * Constructor * @param $color string : color of car * @param $doorNumber int : number of door */ function __construct($color, $doorNumber) { $this->color = $color; $this->doorNumber = $doorNumber; } /** * Start a car */ public function start() { // TODO : create code } /** * Stop a car */ public function stop() { // TODO : create code } /** * Turn on or turn off headlights for a car * @param $toogle boolean Turn on or turn off headlights */ public function toggleHeadlights($toogle) { // TODO : create code } } Dorénavant, pour créer un objet, il faudra lui transmettre ce que le constructeur attend. .. code-block:: php Car porsche = new Car("green", 5); Et le code dans cette méthode, il sert à quoi ? C’est quoi ces $this ? Encore un mot-clé : $this ------------------------- Une ou plusieurs propriétés sont contenues dans une classe (ex : $color, $doorNumber). Elles doivent pouvoir être utilisées et même réutilisées si nécessaire. Au moment de l’instanciation de l’objet, le constructeur permet de lier la couleur choisie à l’intérieur de l’objet. Pour stocker la couleur de la propriété dans l’objet et pas dans une variable quelconque, le mot clé $this est utilisé pour préciser que la variable à utiliser est celle contenue dans la classe. Le mot-clé $this correspond en fait à un objet instancié, présent en mémoire, c’est une référence sur celui-ci à partir d’une définition de classe. Une classe nous permet d’instancier plusieurs objets, le mot-clé $this correspondra donc à l’instance de l’objet en cours. D’ailleurs, ce mot-clé est également utilisé pour appeler une méthode interne à la classe et doit être explicitement ajouté lorsqu’il peut y avoir confusion. La visibilité des propriétés et des méthodes -------------------------------------------- Depuis le début de ce document, les mots-clés private, protected et public sont notés devant les propriétés et méthodes. Mais à quoi servent-ils ? Ils définissent la visibilité des propriétés ou méthodes d’un objet au sein d’un programme. private : accessible uniquement depuis l’intérieur de la classe protected : accessible depuis l’intérieur de la classe et les descendants (héritage) public : accessible à l’extérieur et à l’intérieur de la classe Prenons un exemple pour illustrer ce cas. Dans les anciennes voitures, le conducteur a la possibilité d’allumer les phares en tournant un bouton par exemple. La méthode « allumer les phares » doit être accessible pour le conducteur, elle a le mot-clé public. PHP : Le conducteur démarre la voiture et allume les phares, il se trouve en dehors de la classe et appelle une méthode de la classe .. code-block:: php $porsche->start(); $porsche->toggleHeadlights(true); Dans une nouvelle voiture, les phares vont s’allumer automatiquement au démarrage. Le conducteur n’a pas besoin d’avoir un bouton, c’est la voiture qui le fait pour lui. La méthode « allumer les phares » a le mot-clé private. Elle est accessible uniquement dans l’objet. PHP : cette fois, c’est au démarrage de la voiture que les phares s’allument automatiquement. Le conducteur ne fait que démarrer la voiture. .. code-block:: php $porsche->start(); PHP : La méthode start appelle la méthode allumer les phares dans la classe Car. .. code-block:: php class Car { […Code avant non changé…] /// /// Start a car /// public function start() { $this->toggleHeadlights(true); // TODO : create code } […Code après non changé…] } Getter et Setter ---------------- Ce qui est appelé Getter et Setter sont des méthodes permettant d’accéder aux attributs d’une classe. Pour l’instant, notre classe a deux propriétés : $color et $doorNumber. Ces dernières sont de visibilité privée. Il n’est pas possible d’y accéder depuis l’extérieur. Si un jour, nous désirons repeindre notre voiture, il serait bien de pouvoir changer sa couleur. Les langages de programmation ont mis en plus ce que l’on nomme Getter et Setter. Voici leur définition : Getter : méthode permettant d’accéder à la valeur d’une propriété = obtenir sa valeur Setter : méthode permettant d’inscrire la valeur d’une propriété Et concrètement, comment se code ces méthodes ? L’idée de base est d’avoir un attribut privé et une méthode publique pour y accéder ou le modifier. Ainsi on aurait par exemple : .. code-block:: php class Car { // Properties private $color; /** * Getter getColor Return the current color or ‘orange’ if not set * @return string */ public function getColor() { if ($this->color==null) return "orange"; return $this->color; } /** * Setter setColor Set to the given color if not null * @param $color * @return void */ public function setColor($color) { if ($color!=null) $this->color=$color; } } Dans certains langages, il existe des différences pour écrire des getters et setters (notamment en C# qui permet une implémentation plus standardisée). En PHP, il existe des getters et setters magiques (standardisés), mais ils ne sont pas utilisés car ils sont plus long à l’interprétation et ne permettent pas d’autocomplétions des éditeurs. Vie et mort d’un objet ---------------------- En résumé, un objet prend vie quand une instance de sa classe est créée. Ce mécanisme prend effet grâce au mot-clé new qui appelle une méthode spéciale nommée constructeur. Cet objet est stocké en mémoire. Donc, ma voiture est créée, mais maintenant elle est vieille et doit passer à la casse, je fais comment pour la détruire ? Quand l’objet n’est plus utilisé, la mémoire qu’il utilise pour son stockage ne peut pas servir à autre chose tant que l’objet est toujours présent (référence utilisée dans le programme). Tout comme, il est impossible de parquer une voiture sur une place où une voiture est déjà parquée. Dans les langages de programmation modernes, la destruction d’un objet se fait de manière automatique via le garbage collector ou ramasse-miettes géré par le langage. L’avantage de détruire un objet qui n’est plus utilisé est de libérer des ressources mémoires. En effet, tout objet créé utilise de la mémoire pour être stocké (tout comme une voiture utilise un espace pour être parquée). Il est néanmoins possible de forcer la destruction d’un objet de cette manière : .. code-block:: php $porsche = null; Héritage -------- L’héritage permet une réutilisation de classes déjà écrites, c’est-à-dire une réutilisation de la structure des données et des méthodes créées. Lorsque plusieurs objets ont des caractéristiques et/ou des comportements communs, la création d’une classe de base (ou parent) permet de regrouper ce qui est semblable. Si nous prenons l’exemple de notre classe Car, une voiture appartient à un parent Vehicle. Le véhicule permet de définir le nombre de roues pour tout type de véhicule. .. code-block:: php class Vehicle { protected $numberOfWheels; public function getNumberOfWheels() { if ($this->numberOfWheels==null) return 4; return $this->numberOfWheels; } /** * Setter setColor Set to the given color if not null * @param $color * @return void */ public function setNumberOfWheels($numberOfWheels) { if ($numberOfWheels != null) $this->numberOfWheels = $numberOfWheels; } } Maintenant, nous aimerions pouvoir avoir le nombre de roues dans notre classe Car. Nous pourrions ajouter un attribut pour définir notre nombre de roues ou alors nous pourrions utiliser le parent Vehicle. Pour lier notre Vehicule à notre Car, nous utilsons le mot-clé « extends ». Cela s’appelle l’héritage. Une classe hérite d’une autre classe. .. code-block:: php class Car extends Vehicle { // TODO : Code } Maintenant, dans en instanciant un objet de ma classe Car, je pourrais définir le nombre de roues. .. code-block:: php $porsche = new Car("red", 5); $porsche->getNumberOfWheels(4); Dans cette partie, vous trouverez principalement la syntaxe de la programmation orienté objet. **Classe** ========== Déclaration d'une classe avec deux propriétés, un constructeur, des getter/setter et une méthode. .. code-block:: php // Nom du fichier : Car.php class Car { // Variables de classe protected $color; // couleur private $vinNumber; // numéro de chassis /** * Constructeur * @param $vinNumber */ function __construct($vinNumber){ $this->setVinNumber($vinNumber); } /** * Getter color * @return string */ public function getColor(){ return $this->color; } /** * Setter color * @param $color */ public function setColor($color){ $this->color = $color; } /** * Getter vinNumber * @return string */ public function getVinNumber(){ return $this->vinNumber; } /** * Setter vinNumber * @param $vinNumber */ private function setVinNumber($vinNumber){ $this->vinNumber = $vinNumber; } /** * Méthode permettant de démarrer la voiture */ public function start(){ // Instruction } } **Héritage** ============ Le mot-clé extends doit être utilisé. Un seul héritage à la fois est autorisé. .. code-block:: php // Nom du fichier : Vehicle.php // Création d'une classe parente class Vehicle { private $numberOfSeats; /** * Getter numberOfSeats * @return string */ public function getNumberOfSeats(){ return $this->numberOfSeats; } /** * Setter numberOfSeats * @param $numberOfSeats */ private function setNumberOfSeats($numberOfSeats){ $this->numberOfSeats = $numberOfSeats; } } .. code-block:: php // Nom du fichier : Car.php // Inclure le fichier parent require('Vehicle.php'); // Héritage de la classe véhicule à la classe voiture class Car extends Vehicle {} **Interface** ============= Le mot-clé implements doit être utilisé. Il est possible d'implémenter plusieurs interfaces. .. code-block:: php //Nom du fichier : IMovable.php // Création d'une interface de mouvement interface IMovable { public function turnRight(); public function turnLeft(); } .. code-block:: php // Nom du fichier : Car.php // Inclure le fichier parent require('IMovable.php'); // Implémentation de l'interface class Car implements iMovable {}