Facebook LinkedIn SourceForge Twitter RSS LastFM
logologo

L'upcasting en PHP

Geoffray Warnants|11/02/2010|5 commentaires

Les problmes de casting (transtypage) sont souvent considrs comme le propre des langages typage fort tels que par exemple Java, C++ ou C#. L'upcasting (communment traduit en franais par "transtypage vers le haut" ou encore "surclassement") consiste transformer une classe drive en une classe dont elle hrite, lui faisant ainsi volontairement perdre de sa spcificit. C'est cette notion d'ascendance qui lui vaut le nom de casting vers le haut, par opposition au downcasting.

Bien que PHP ne puisse pas raliser cette transformation nativement, voyons comme faire pour y remdier en imaginant l'exemple suivant :

class Person
{
}
class Child extends Person
{
}

Ainsi, avec une hirarchie similaire crite en Java, convertir une instance de Child en un objet de type Person aurait pu se faire tout naturellement.

Child c = new Child();
Person m = c;

Ce n'est malheureusement pas pareil en PHP, puisque comme l'indique la documentation sur le type casting, seule la conversion vers les types natifs est possible. La tentative suivante se solderait donc par une erreur de syntaxe.

$c = new Child();
$m = (Person)$c;

Pour remdier ce problme, je m'inspire ici du concept de "constructeur de copie" qu'on retrouve en C++ et qui a pour but de raliser une copie d'un objet via le constructeur de la classe. Bien souvent, la copie consiste tout btement en une initialisation dite membre membre. On peut donc ajouter la classe mre un constructeur jouant ce rle :

class Person
{
    /**
     * Constructeur de copie
     */
    public function __construct(Person $c=null)
    {
        if ($c !== null) {
            foreach (get_object_vars($c) as $property => $value) {
                if (!is_object($value)) {
                    $this->$property = $value;
                } else {
                    $this->$property = clone $value;
                }
            }
        }
    }
}

On peut alors simuler l'upcasting :

$c = new Child();
$m = new Person($c);

Un tel besoin peut paratre droutant, puisque en ralit, une instance de Child est dj par hritage une instance de Person, laquelle des spcificits sont apportes. Nanmoins, dans certains cas, il peut s'avrer utile de retirer les atouts d'une instance drive pour n'en retrouver que les comportement et proprits hrites. Par exemple, une mthode qui accepte un objet en paramtre pourrait interdire la rception d'une classe drive dont les caractristiques seraient juges inopportunes.

class Person
{
    public function haveSex(Person $p)
    {
        if ($p instanceof Child) {
            throw new Exception('Tu devrais pas tre au lit toi ?');
        }
        // n'golo golo !
    }
}

Finalement, voici comment conclure par un malheureux inceste programmatique ;)

$serge = new Person();
$charlotte = new Child();
$serge->haveSex(new Person($charlotte));

<<< Retour

Vos commentaires

4 commentaires posts

Skye
17/03/2021 11:21Post par Skye
I'm amazed, I have to admit. Seldom do I encounter a blog
that's equally educative and engaging, and without a doubt, you've hit
the nail on the head. The problem is something too few men and women are speaking intelligently
about. I'm very happy I stumbled across this in my search for something concerning this.
Eunice Guerin
21/12/2020 10:48Post par Eunice Guerin
Souvent, lorsqu?on ?crit un programme C++ avec une dizaine de classes, on a des probl?mes avec les d?placements entre eux. Peut-?tre votre article peut m?aider ? r?soudre ce l?ger souci. Merci beaucoup pour ce travail.
Joanna Vidal
25/08/2020 07:16Post par Joanna Vidal
C?est la première fois que je visite votre blog. Et je trouve que vos articles sont destinés aux informaticiens. Pour ma part, si je veux installer quelque chose dans mon ordinateur, je demande à une amie qui connait très bien l?informatique.
syboatnot
29/07/2011 15:08Post par syboatnot
tres interessant, merci

Ragir cet article

*


(Ne sera pas publie, servira uniquement afficher votre gravatar)


(Lien en dur et dofollow)

zend framework