Polymorphisme et PHP5

Le polymorphisme est un concept majeur de la Programmation Orientée Objet (POO). Des langages mûrs tels que C++ ou JAVA intègrent ce concept de manière native. PHP5 permet également d’intégrer le polymorphisme dans le développement PHP.

Qu’est-ce que le polymorphisme?

Son principe réside dans son nom : [poly-] signifie beaucoup et [-morphisme] signifie formes, états. Ainsi, intégrer le polymorphisme dans la programmation permet au développeur d’initialiser un seul objet qui se comportera différemment selon son type. Pratiquement parlant, le développeur écrit une classe de base qui définit les attributs de l’objet et autant de sous-classes que de comportements différents de l’objet seront nécessaires.

Voici un exemple simple de design polymorphique dans le cadre d’un objet véhicule. La classe véhicule a pour attributs des informations qui valent pour tout type de véhicule : marque, date d’achat, prix d’achat :

Class Vehicule {

 

protected $marque;
protected $date_achat;
protected $prix_achat;
public function __construct($marque,$date_achat,$prix_achat) {
$this->marque = $marque;
$this->date_achat = $date_achat;
$this->prix_achat = $prix_achat;
}

}

On peut ensuite créer la classe avion et la classe voiture héritant de la classe véhicule :

Class Voiture Extends Vehicule {

private $cylindree;
private $km;
public function __construct($array) {
parent::__construct($array["marque"],$array["date_achat"],$array["prix_achat"]);
$this->cylindree = $array["cylindree"];
$this->km = $array["km"];
}
}

Class Avion Extends Vehicule {

private $type;
private $heures_vol;
public function __construct($array) {
parent::__construct($array["marque"],$array["date_achat"],$array["prix_achat"]);
$this->type = $array["type"];
$this->heures_vol = $array["heures_vol"];
}

}

Structurer vos classes de cette manière permet de rendre votre programmation orientée objet plus abstraite, et donc plus flexible. Changer un type d’objet particulier après production sera plus aisé et plus stable.

Objets sans design polymorphique

Créer une classe de génération de champs de formulaire sans polymorphisme :

<?php
class Form {
public function genInput($type,$name,$value) {
SWITCH($type) {
Case”text”:
print “<input type=\”text\” name=\”".$name.”\” value=\”".$value.”\” />\r\n”;
break;
Case”textarea”:
print “<textarea name=\”".$name.”\”>”.$value.”</textarea>\r\n”;
break;
}
}
}
$form = new Form(); //initialisation de l’objet formulaire
$form->genInput(“text”,”field1″,”Lorem ipsum…”); //affiche <input type=”text” name=”field1″ value=”Lorem ipsum…” />
$form->genInput(“textarea”,”field2″,”Lorem ipsum…”); //affiche <textarea name=”field2″>Lorem ipsum…</textarea>
?>

Objets avec design polymorphique

Pour qu’un objet puisse revêtir plusieurs formes, qu’il s’agisse d’un champ texte ou d’un champ textarea, nous devons rendre notre classe plus abstraite.
Nous allons donc créer une interface, une classe abstraite et quelques sous-classes (selon le type de champ).
L’interface définira les fonctions que l’objet appellera sans définir ce que ces fonctions feront. L’interface ne définira aucune des fonctionnalités de ces méthodes, elle se contente de les nommer. Chaque sous-classe devra comporter la définition de la méthode genInput().

//INTERFACE
interface Form {

public function genInput();

}

Une classe abstraite est une classe qui nous n’implémentons que partiellement. Elle contient les méthodes (fonctions) abstraites qui offrent des fonctionnalités communes. Le reste des autres fonctioannlités sera défini dans les sous-classes.
//ABSTRACT CLASS
abstract class Input {
protected $name;
protected $value;
public function __construct($name,$value) {
$this->name = $name;
$this->value = $value;
}
}
Puis les classes dérivées appelleront la méthode définie dans la classe abstraite (parent::__construct()) et la méthode nommée dans l’interface (genInput()) :
//TEXT & PASSWORD & HIDDEN INPUT
class Text extends Input implements Form {
private $type;
private $size;
public function __construct($array) {
parent::__construct($array["name"],$array["value"]);
$this->type = $array["type"];
$this->size = $array["size"];
}
public function genInput() {
return “<input type=\”".$this->type.”\” name=\”".$this->name.”\” value=\”".$this->value.”\” size=\”".$this->size.”\” />\r\n”;
}
}
//TEXTAREA INPUT
class Textarea extends Input implements Form {
private $cols;
private $rows;
public function __construct($array) {
parent::__construct($array["name"],$array["value"]);
$this->cols = $array["cols"];
$this->rows = $array["rows"];
}
public function genInput() {
return “<textarea name=\”".$this->name.”\” cols=\”".$this->cols.”\” rows=\”".$this->rows.”\”>”.$this->value.”</textarea>\r\n”;
}
}
Voici comment créer un champ texte :
$object = new Text(array(“type”=>”text”,”name”=>”form_id”,”value”=>$item,”size”=>20));
$hidden = $object->genInput();
Générer un champ textarea ressemble à ceci :
$object = new Textarea(array(“name”=>”form_txta”,”value”=>$item ,”cols”=>20 ,”rows”=>5));
$textarea = $object->genInput();
Webliography :

Abstract classes and interfaces
Devshed polymorphism in PHP5 article
PHP5 Tutorial : Abstract classes and Interfaces
PHP5 OOP abstract classes & interfaces

Polymorphism in PHP5

Polymorphism is one of the major Object Oriented Programming features (OOP) mature programming languages like C++ or JAVA implement. Though OOP experts may reasonably claim that PHP is not strictly Object Oriented (since nothing is an object in PHP unless you create it), the language has become polymorphism-ready with version PHP5.

What is polymorphism?

Its principle lies in its name : [poly-] means much, many and [-morphism] means forms, states. So, programming in a polymorphic way allows the developer to have one single object behaving differently according to its type. Practically speaking, the developer writes a base class which defines the basic features of the object and as many subclasses as necessary to build the different behaviours the object may have. Calling the same method will have the object’s children behave differently.

Here is a simple example of polymorphic design with a vehicle object. The Vehicle class has as attributes pieces of information that are found in every kind of vehicle : make, registering date, price :

Class Vehicle {

 

protected $make;
protected $date;
protected $price;
public function __construct($make,$date,$price) {
$this->make = $make;
$this->date= $date;
$this->price= $price;
}

}

Then create the plane class and the car class that will inherit the vehicle class :

Class Car Extends Vehicle {

private $engine;
private $mileage;
public function __construct($array) {
parent::__construct($array["make"],$array["date"],$array["price"]);
$this->engine = $array["engine"];
$this->mileage = $array["mileage"];
}
}

Class Plane Extends Vehicule {

private $type;
private $seats;
public function __construct($array) {
parent::__construct($array["make"],$array["date"],$array["price"]);
$this->type = $array["type"];
$this->seats = $array["seats"];
}

}

Structuring your classes that way allows you to make your OOP more abstract, thus more flexible. Changing a specific type of object after production time will be made easier and more stable.

Objects without polymorphic design

Imagine you want to create a form generator class without polymorphism :

<?php
class Form {
public function genInput($type,$name,$value) {
SWITCH($type) {
Case”text”:
print “<input type=\”text\” name=\”".$name.”\” value=\”".$value.”\” />\r\n”;
break;
Case”textarea”:
print “<textarea name=\”".$name.”\”>”.$value.”</textarea>\r\n”;
break;
}
}
}
$form = new Form(); //initialize form object
$form->genInput(“text”,”field1″,”Lorem ipsum…”); //prints <input type=”text” name=”field1″ value=”Lorem ipsum…” />
$form->genInput(“textarea”,”field2″,”Lorem ipsum…”); //prints <textarea name=”field2″>Lorem ipsum…</textarea>
?>

Objects with polymorphic design

In order to allow an object to have several forms, be it a text field or a textarea field, we need to make our class more abstract.
So, we will create an interface, an abstract class and several subclasses (depending on the type of field).
The interface will define the functions the object will perform, no matter what the function will do. But the interface will not define any functionality of the methods, it only names them. The precise functionalities of the genInput() function will be defined in every subclass.

//INTERFACE
interface Form {

public function genInput();

}

The abstract class is a class that we only partially implement. It contains abstract methods (functions) that provide some common functionalities. The rest of the necessary functionalities will be defined in the subclasses.
//ABSTRACT CLASS
abstract class Input {
protected $name;
protected $value;
public function __construct($name,$value) {
$this->name = $name;
$this->value = $value;
}
}
Then the derived classes will call the method set in the abstract class (parent::__construct()) and the method named in the interface (genInput()) :
//TEXT & PASSWORD & HIDDEN INPUT
class Text extends Input implements Form {
private $type;
private $size;
public function __construct($array) {
parent::__construct($array["name"],$array["value"]);
$this->type = $array["type"];
$this->size = $array["size"];
}
public function genInput() {
return “<input type=\”".$this->type.”\” name=\”".$this->name.”\” value=\”".$this->value.”\” size=\”".$this->size.”\” />\r\n”;
}
}
//TEXTAREA INPUT
class Textarea extends Input implements Form {
private $cols;
private $rows;
public function __construct($array) {
parent::__construct($array["name"],$array["value"]);
$this->cols = $array["cols"];
$this->rows = $array["rows"];
}
public function genInput() {
return “<textarea name=\”".$this->name.”\” cols=\”".$this->cols.”\” rows=\”".$this->rows.”\”>”.$this->value.”</textarea>\r\n”;
}
}
This is how you can create a text field :
$object = new Text(array(“type”=>”text”,”name”=>”form_id”,”value”=>$item,”size”=>20));
$hidden = $object->genInput();
Generating a textarea field looks like this :
$object = new Textarea(array(“name”=>”form_txta”,”value”=>$item ,”cols”=>20 ,”rows”=>5));
$textarea = $object->genInput();
Webliography :

Abstract classes and interfaces
Devshed polymorphism in PHP5 article
PHP5 Tutorial : Abstract classes and Interfaces
PHP5 OOP abstract classes & interfaces