Facebook LinkedIn SourceForge Twitter RSS LastFM
logologo

L'upcasting en PHP

Geoffray Warnants|11/02/2010|2 commentaires

Les problèmes de casting (transtypage) sont souvent considérés comme le propre des langages à typage fort tels que par exemple Java, C++ ou C#. L'upcasting (communément traduit en français par "transtypage vers le haut" ou encore "surclassement") consiste à transformer une classe dérivée en une classe dont elle hérite, lui faisant ainsi volontairement perdre de sa spécificité. 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 réaliser cette transformation nativement, voyons comme faire pour y remédier en imaginant l'exemple suivant :

class Person
{
}
class Child extends Person
{
}

Ainsi, avec une hiérarchie 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 remédier à ce problème, je m'inspire ici du concept de "constructeur de copie" qu'on retrouve en C++ et qui a pour but de réaliser une copie d'un objet via le constructeur de la classe. Bien souvent, la copie consiste tout bêtement en une initialisation dite membre à membre. On peut donc ajouter à la classe mère un constructeur jouant ce rôle :

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 paraître déroutant, puisque en réalité, une instance de Child est déjà par héritage une instance de Person, à laquelle des spécificités sont apportées. Néanmoins, dans certains cas, il peut s'avérer utile de retirer les atouts d'une instance dérivée pour n'en retrouver que les comportement et propriétés héritées. Par exemple, une méthode qui accepte un objet en paramètre pourrait interdire la réception d'une classe dérivée dont les caractéristiques seraient jugées 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

1 commentaire posté

syboatnot
29/07/2011 15:08Posté par syboatnot
tres interessant, merci

Réagir à cet article

*


(Ne sera pas publiée, servira uniquement à afficher votre gravatar)


(Lien en dur et dofollow)

zend framework