• 10 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

Ce cours existe en livre papier.

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 21/08/2023

Découvrez comment profiter des propriétés et méthodes dont votre classe vient d’hériter

Maintenant que vous savez pourquoi et comment mettre en place l’héritage, nous allons découvrir comment profiter des propriétés et méthodes héritées. :)

Accédez aux propriétés de la classe parente

Lorsque vous utilisez l'héritage, depuis l'objet comme depuis la classe, vous pouvez accéder aux propriétés de la classe parente de la même manière qu'avant, avec la flèche   -> , comme vous pouvez le voir à la ligne 22 :

<?php
 
declare(strict_types=1);
 
class User
{
    public const STATUS_ACTIVE = 'active';
    public const STATUS_INACTIVE = 'inactive';
 
    public function __construct(public string $username, public string $status = self::STATUS_ACTIVE)
    {
    }
}
 
class Admin extends User
{
    // ...
 
    public function printStatus()
    {
        // vous pouvez accéder au statut comme si la propriété appartenait à Admin :)
        echo $this->status;
    }
}
 
$admin = new Admin('Lily');
$admin->printStatus();

Tester ce code

Il en va de même pour les propriétés statiques.

Depuis la classe enfant, vous pourrez faire référence aux mêmes propriétés statiques que le parent, peu importe que vous fassiez référence à la classe enfant ou à la classe parente. En revanche, ceci marche en cascade : vous ne pourrez pas faire référence aux propriétés (statiques ou non) de l'enfant depuis le parent. Voyez ceci comme des poupées russes. Les parents sont au centre. Vous pourrez atteindre un parent en passant par un enfant, l’inverse n’est pas vrai.

Pour faire référence à un parent, vous devez utiliser le nouveau mot clé parent. Il permet de faire référence à une classe parente. En revanche, lorsque votre classe hérite d’une classe, qui elle-même hérite d’une classe, qui elle-même… bref, vous ne pouvez pas cibler la classe parente désirée, avec le mot clé   parent  vous remontez (PHP remonte tel un saumon) l’arbre généalogique, jusqu'à trouver l’élément parent auquel vous faites référence. S’il s’agit d’une méthode, elle peut alors elle aussi faire référence à un parent. :)

<?php
 
declare(strict_types=1);
 
class User
{
    public const STATUS_ACTIVE = 'active';
    public const STATUS_INACTIVE = 'inactive';
 
    public static $nombreUtilisateursInitialisés = 0;
 
    public function __construct(public string $username, public string $status = self::STATUS_ACTIVE)
    {
    }
}
 
class Admin extends User
{
    public static $nombreAdminInitialisés = 0;
 
    // mise à jour des valeurs des propriétés statiques de la classe courante avec `self`, et de la classe parente avec `parent`
    public static function nouvelleInitialisation()
    {
        self::$nombreAdminInitialisés++; // classe Admin
        parent::$nombreUtilisateursInitialisés++; // classe User
    }
}
 
Admin::nouvelleInitialisation();
var_dump(Admin::$nombreAdminInitialisés, Admin::$nombreUtilisateursInitialisés, User::$nombreUtilisateursInitialisés);
var_dump(User::$nombreAdminInitialisés); // ceci ne marche pas.

Tester ce code 

Accédez aux méthodes de la classe parente

En ce qui concerne les méthodes de classe, depuis un objet, tout comme les accès aux propriétés, rien ne change. Vous pourrez accéder aux méthodes de la même manière qu'avant, avec la flèche   ->  comme vous pouvez le voir à la ligne 28 :

<?php

declare(strict_types=1);

class User
{
    public const STATUS_ACTIVE = 'active';
    public const STATUS_INACTIVE = 'inactive';

   public function __construct(public string $username, public string $status = self::STATUS_ACTIVE)
    {
    }

    public function printStatus()
    {
        echo $this->status;
    }
}


class Admin extends User
{
    // ...

    public function printCustomStatus()
    {
        echo “L’administrateur {$this->username} a pour statut : “;
        $this->printStatus(); // on appelle printStatus du parent depuis la classe enfant
    }

}


$admin = new Admin('Lily');
$admin->printCustomStatus(); // Affiche “L’administrateur Lily a pour statut : active”
$admin->printStatus(); // printStatus n’existe pas dans la classe Admin, donc printStatus de la classe User sera appelée grâce à l’héritage

PHP vous permet également de réécrire une méthode existante d’un parent, dans une classe enfant. On parle de surcharge

Que vous permet de faire PHP, et que vous impose-t-il lorsque vous réécrivez/surchargez une méthode existante dans une classe parente ? Pour commencer, sa signature doit rester compatible avec la méthode d'origine :

  • vous ne pouvez pas enlever des arguments ;

  • vous pouvez ajouter un argument uniquement s'il est optionnel ;

  • Vous pouvez changer le type d'un argument uniquement s'il est compatible avec le type d'origine (voir un exemple) ;

  • vous pouvez changer le type de retour de la méthode uniquement s'il est compatible avec le type d'origine.

Lorsque vous surchargez une méthode, vous pouvez choisir d’exploiter la méthode parente et d’ajouter un comportement supplémentaire, ou de choisir de complètement réécrire le comportement. Dans le premier cas, lorsque vous souhaitez appeler la méthode parente, plutôt que la flèche, il faut utiliser parent::.

<?php
 
declare(strict_types=1);
 
class User
{
    public const STATUS_ACTIVE = 'active';
    public const STATUS_INACTIVE = 'inactive';
 
    public function __construct(public string $username, public string $status = self::STATUS_ACTIVE)
    {
    }
 
    public function setStatus(string $status): void
    {
        if (!in_array($status, [self::STATUS_ACTIVE, self::STATUS_INACTIVE])) {
            trigger_error(sprintf('Le status %s n\'est pas valide. Les status possibles sont : %s', $status, implode(', ', [self::STATUS_ACTIVE, self::STATUS_INACTIVE])), E_USER_ERROR);
        };
 
        $this->status = $status;
    }
 
    public function getStatus(): string
    {
        return $this->status;
    }
}
 
class Admin extends User
{
    public const STATUS_LOCKED = 'locked';
 
    // la méthode est entièrement réécrite ici :) seule la signature reste inchangée
    public function setStatus(string $status): void
    {
        if (!in_array($status, [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_LOCKED])) {
            trigger_error(sprintf('Le status %s n\'est pas valide. Les status possibles sont : %s', $status, implode(', ', [self::STATUS_ACTIVE, self::STATUS_INACTIVE, self::STATUS_LOCKED])), E_USER_ERROR);
        };

        $this->status = $status;
    }
 
    // la méthode utilisée est celle de la classe parente, puis ajoute un comportement :)
    public function getStatus(): string
    {
        return strtoupper(parent::getStatus());
    }
}
 
$admin = new Admin('Paddington');
$admin->setStatus(Admin::STATUS_LOCKED);
echo $admin->getStatus();

Tester ce code

Comme vous avez pu le voir dans l’exemple précédent ciblant une propriété parente, lorsqu’une méthode est héritée depuis une classe enfant, vous pouvez choisir :

  • d’appeler la méthode de la classe courante avec  $this  (ou  self  pour les méthodes statiques) ;

  • ou bien de cibler la méthode parente avec le mot clé  parent::.

Exercez-vous

Dans cet exercice, le code de la salle d'attente (la classe   Lobby) existe, ainsi que le code d'un joueur (la classe   Player). Lorsqu'un joueur s'enregistre dans le Lobby, il devient un Joueur en Attente.

Un joueur en attente possède une propriété  range  qui est un entier. Le but de cette propriété est d'accroître la portée de la recherche d'un adversaire, lorsqu'aucun ne correspond au niveau du joueur. Le but étant de trouver un adversaire, quitte à ce qu'il soit plus faible ou plus fort.

Votre tâche est de :

  • créer une classe QueuingPlayer  qui étend la classe Player ;

  • et de lui ajouter la propriété range.

Vous trouverez le code de l’exercice sur la branche P2C2, et la correction sur la branche P2C2-correction. :)

En résumé

  • La façon d’accéder aux propriétés des classes parentes s’effectue avec la flèche ->.

  • La façon d’accéder aux méthodes des classes parentes s’effectue également à l’aide de la flèche ->.

  • Lorsqu’il s’agit d’une méthode ou d’une propriété statique parente, l’accès s’effectue avec le mot clé parent.

  • Vous pouvez ré-écrire une méthode existante dans un enfant, à condition de respecter sa signature.

Réduire notre code grâce à l’héritage est une bonne chose, mais avec le temps vous vous apercevrez que les visibilités public ou private ne sont plus suffisantes. Regardons comment limiter l’accès aux propriétés et aux méthodes avec l’héritage, dans le chapitre suivant. C’est parti !

Exemple de certificat de réussite
Exemple de certificat de réussite