Nouveau modèle objet
La gestion des objets a été complètement réécrite permettant d’obtenir des meilleures performances et d’utiliser plus de fonctionnalités objet.
Dans les versions précédentes de PHP, les objets étaient gérés comme des primitives (integers, strings). Avec cette méthode, l’objet était copié dans son intégralité. Dans la nouvelle approche, les objets sont gérés par référence et non copiés par valeur lors de l’assignation à une variable.
Variables privées et protégées
PHP 5 introduit les variables privées et protégées, ce qui permet de définir la visibilité des propriétés d’une classe.
Les variables protégées peuvent être accédées uniquement par les classes descendantes de la classe dans laquelle ces dernières sont déclarées alors que les variables privées ne sont accessibles que par la classe même dans laquelle elles sont déclarées.
<?php
class MyClass {
private $Hello = "Hello, World!\n";
protected $Bar = "Hello, Foo!\n";
protected $Foo = "Hello, Bar!\n";
function printHello() {
print "MyClass::printHello() " . $this->Hello;
print "MyClass::printHello() " . $this->Bar;
print "MyClass::printHello() " . $this->Foo;
}
}
class MyClass2 extends MyClass {
protected $Foo;
function printHello() {
MyClass::printHello(); /* Affichage OK */
print "MyClass2::printHello() ".$this->Hello; /* Aucun affichage */
print "MyClass2::printHello() ".$this->Bar; /* Aucun affichage */
print "MyClass2::printHello() ".$this->Foo; /* Aucun affichage */
}
}
$obj = new MyClass();
print $obj->Hello; /* Aucun affichage */
print $obj->Bar; /* Aucun affichage */
print $obj->Foo; /* Aucun affichage */
$obj->printHello(); /* Affichage OK */
$obj = new MyClass2();
print $obj->Hello; /* Aucun affichage */
print $obj->Bar; /* Aucun affichage */
print $obj->Foo; /* Aucun affichage */
$obj->printHello();
?>
Méthodes privées et protégées
Avec PHP 5, les méthodes privées et protégées sont également introduites :
<?php
class Foo {
private function aPrivateMethod() {
echo "Foo::aPrivateMethod() called.\n";
}
protected function aProtectedMethod() {
echo "Foo::aProtectedMethod() called.\n";
$this->aPrivateMethod();
}
}
class Bar extends Foo {
public function aPublicMethod() {
echo "Bar::aPublicMethod() called.\n";
$this->aProtectedMethod();
}
}
$o = new Bar;
$o->aPublicMethod();
?>
L’ancien code qui ne possède pas de classes ou fonctions nomenclaturées public
,
protected
ou private
ne doit poser aucun problème de
migration.
Classes abstraites et méthodes
PHP 5 introduit également les méthodes et classes abstraites. Une méthode
abstraite déclare uniquement la signature de la méthode et ne fournit pas
d’implémentation. Une classe qui contient des méthodes abstraites doit être
déclarée avec le mot clé abstract
.
<?php
abstract class AbstractClass {
abstract public function test();
}
class ImplementedClass extends AbstractClass {
public function test() {
echo "ImplementedClass::test() called.\n";
}
}
$o = new ImplementedClass;
$o->test();
?>
Les classes abstraites ne peuvent être instanciées. L’ancien code ne
possédant pas le mot clé abstract
ne doit poser aucun problème au cours de la
migration.
Interfaces
Zend Engine 2.0 introduit les interfaces. Une classe peut implémenter une liste arbitraire d’interfaces.
<?php
interface Throwable {
public function getMessage();
}
class Exception implements Throwable {
public function getMessage() {
// ...
}
}
?>
L’ancien code ne possédant pas le mot clé interface
ou implements
ne
doit poser aucun problème au cours de la migration.
Final
PHP 5 introduit le mot clé final pour déclarer des méthodes et variables
finales. Les méthodes et variables déclarées final
ne peuvent pas être
overridés par des classes descendantes.
<?php
class Foo {
final function bar() {
// ...
}
}
?>
L’ancien code ne possédant pas le mot clé final
ne doit poser aucun
problème au cours de la migration.
Clônage d’objets
PHP 4 (Zend Engine 1.0) n’offrait aucun contrôle sur la copie d’un objet. Durant la duplication, PHP4 effectuait une copie bit par bit pour construire un réplicat identique (propriétés, méthodes, etc.).
La création d’une copie d’un objet avec toutes les propriétés répliquées
n’est pas toujours le comportement souhaité, c’est pourquoi la méthode __clone()
est offerte avec PHP 5.
Une copie d’objet est réalisée avec la méthode __clone()
:
<?php
$copy_of_object = $object->__clone();
?>
Lors de l’appel de cette méthode, Zend Engine v 2.0 vérifie si la méthode
__clone()
a été définie ou pas. Dans le cas contraire, la méthode __clone()
par défaut est appelée, laquelle effectue une copie de toutes les propriétés de
l’objet. Lorsque la méthode __clone()
est définie, cette dernière permet de
définir explicitement la copie des propriétés dans l’objet créé : ceci permet
d’overrider uniquement les propriétés qui nécessitent d’être changées.
<?php
class MyCloneable {
static $id = 0;
function MyCloneable() {
$this->id = self::$id++;
}
function __clone() {
$this->name = $that->name;
$this->address = "New York";
$this->id = self::$id++;
}
}
$obj = new MyCloneable();
$obj->name = "Hello";
$obj->address = "Tel-Aviv";
print $obj->id . "\n";
$obj = $obj->__clone();
print $obj->id . "\n";
print $obj->name . "\n";
print $obj->address . "\n";
?>
Constructeurs unifiés
Avec PHP 4, les méthodes constructor étaient des méthodes qui avaient le même nom que la class, ceci posait des problèmes pour appeler les constructeurs du parent.
PHP 5 introduit une nouvelle voie pour déclarer des constructeurs en
appelant la méthode __construct()
.
<?php
class BaseClass {
function __construct() {
print "In BaseClass constructor\n";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructor\n";
}
}
$obj = new BaseClass();
$obj = new SubClass();
?>
Pour des raisons de compatibilité, si PHP 5 ne trouve pas de méthode
__construct()
pour une classe donnée, l’ancienne méthode constructeur PHP 4 est
cherchée (méthode du même nom que la classe).
Destructeurs
Avoir la possibilité de définir des destructeurs pour des objets peut être très utile. Les destructeurs permet de logger des messages, fermer des connexions aux bases de données ou tout autre nettoyage nécessaire.
PHP 5 introduit le concept de destructeur comme les autres langages de
programmation. La méthode __destruct()
n’acceptant aucun paramètre est appelé
avant que tout objet ne soit détruit en mémoire.
<?php
class MyDestructableClass {
function __construct() {
print "In constructor\n";
$this->name = "MyDestructableClass";
}
function __destruct() {
print "Destroying " . $this->name . "\n";
}
}
$obj = new MyDestructableClass();
?>
Comme les constructeurs, les destructeurs parent ne sont pas appelés
implicitement par le moteur PHP. Pour exécuter la méthode __destruct()
, il
faut appeler explicitement parent ::__destruct()
.
Constantes
PHP 5 introduit les constantes par classe :
<?php
class Foo {
const constant = "constant";
}
echo "Foo::constant = " . Foo::constant . "\n";
?>
PHP 5 autorise les expressions entre constantes, toutefois les constantes sont évaluées à la compilation, aussi ces dernières ne peuvent être évaluées sur des variables en runtime :
<?php
class Bar {
const a = 1<<0;
const b = 1<<1;
const c = a | b;
}
?>
L’ancien code ne possédant pas le mot clé constant
ne doit poser aucun
problème au cours de la migration.
Exceptions
PHP 4 ne permettait pas la gestion des exceptions, PHP 5 introduit un modèle d’exception similaire aux autres langages de programmation.
<?php
class MyExceptionFoo extends Exception {
function __construct($exception) {
parent::__construct($exception);
}
}
try {
throw new MyExceptionFoo("Hello");
}
catch (MyException $exception) {
print $exception->getMessage();
}
?>
L’ancien code ne possédant pas le mot clé exception
ne doit poser aucun
problème au cours de la migration.
Variables statiques et classes statiques
Les variables statiques et les classes statiques peuvent être maintenant initialisées :
<?php
class foo {
static $my_static = 5;
}
print foo::$my_static;
?>
Méthodes statiques
PHP 5 introduit le mot clé static
pour déclarer une méthode statique,
cette dernière pouvant être appelée en dehors du contexte de l’objet :
<?php
class Foo {
public static function aStaticMethod() {
// ...
}
}
Foo::aStaticMethod();
?>
La pseudo variable $this n’est pas disponible dans une méthode déclarée en statique.
__autoload( )
La fonction __autoload()
est utilisée automatiquement lorsqu’une classe non
déclarée doit être instanciée. Le nom de la classe est automatiquement passée à
la fonction __autoload()
.
<?php
function __autoload($className) {
include_once $className . ".php";
}
$object = new ClassName;
?>
Appels de méthodes surchargeables et accès aux propriétés surchargeables
Les appels de méthodes et les accès aux propriétés peuvent être surchargés
avec les méthodes __call()
,__get()
et __set()
.
Exemples : __get()
et __set()
<?php
class Setter {
public $n;
public $x = array("a" => 1, "b" => 2, "c" => 3);
function __get($nm) {
print "Getting [$nm]\n";
if (isset($this->x[$nm])) {
$r = $this->x[$nm];
print "Returning: $r\n";
return $r;
} else {
print "Nothing!\n";
}
}
function __set($nm, $val) {
print "Setting [$nm]to $val\n";
if (isset($this->x[$nm])) {
$this->x[$nm] = $val;
print "OK!\n";
} else {
print "Not OK!\n";
}
}
}
$foo = new Setter();
$foo->n = 1;
$foo->a = 100;
$foo->a++;
$foo->z++;
var_dump($foo);
?>
Exemple : __call()
<?php
class Caller {
var $x = array(1, 2, 3);
function __call($m, $a) {
print "Method $m called:\n";
var_dump($a);
return $this->x;
}
}
$foo = new Caller();
$a = $foo->test(1, "2", 3.4, true);
var_dump($a);
?>