<?php
class Personnage {
private $force;
private $localisation;
private $experience;
private $degats;
public function __construct($force) {
$this->setForce($force);
$this->experience = 1;
}
public function parler() {
echo 'Je suis un personnage !';
}
public function setForce($force) {
if (!is_int($force)) {
trigger_error('La force doit être un nombre entier', E_USER_WARNING);
return;
}
if ($force > 100) {
trigger_error('La force ne peut dépasser 100', E_USER_WARNING);
return;
}
$this->_force = $force;
}
}
?>
<?php
class Personnage // Déclaration de la classe
{
// Déclaration des attributs et méthodes ici.
}
?>
<?php
class Personnage
{
private $force; // La force du personnage
private $localisation; // Sa localisation
private $experience; // Son expérience
private $degats; // Ses dégâts
}
?>
Historiquement, certains projets préfixaient les éléments privés par un underscore (« _ »). Les conventions modernes (PSR) recommandent d'utiliser la visibilité (private/protected/public) sans underscore.
Les attributs peuvent être initialisés lors de leur déclaration.
<?php
class Personnage
{
private $force = 50;
private $localisation = 'Grenoble';
private $experience = 1;
private $degats = 0;
}
?>
<?php
class Personnage
{
public function deplacer() { }
public function frapper() { }
public function gagnerExperience() { }
}
?>
class.Pour créer et manipuler des objets :
<?php
$perso = new Personnage; // Instanciation d'un objet
$perso->parler(); // Appel d'une méthode
?>
Pour créer et manipuler des objets, on va utiliser le mot-clé new.
La variable $perso sera donc un objet de type Personnage.
On dit que l’on instancie la classe Personnage, ou encore que l’on crée une instance de la classe Personnage.
Pour accéder ou modifier les attributs privés :
<?php
class Personnage
{
public function degats() {
return $this->degats;
}
public function setForce($force) {
if (!is_int($force)) return;
if ($force > 100) return;
$this->force = $force;
}
}
?>
Une méthode spéciale pour initialiser un objet lors de sa création.
<?php
class Personnage
{
public function __construct($force, $degats)
{
$this->setForce($force);
$this->setDegats($degats);
$this->experience = 1;
}
}
$perso1 = new Personnage(60, 0); // 60 de force, 0 dégât
$perso2 = new Personnage(100, 10); // 100 de force, 10 dégâts
?>
La POO sert, entre autres, à pouvoir structurer et organiser le code des applications.
Une bonne pratique consiste à créer un fichier par classe, et de nommer ce fichier avec le nom de la classe. Pour notre classe Personnage par exemple, on va créer un fichier Personnage.php qui contiendra uniquement le code de cette classe.
Ensuite, lorsque l’on voudra utiliser cette classe dans un programme, on pourra utiliser la fonction require:
<?php
require 'MaClasse.php'; // J'inclus la classe.
$objet = new MaClasse; // Puis, seulement après, je me sers de ma classe.
?>
Cette manière de procéder est acceptable sur un tout petit projet avec une ou deux classes. Cependant, une application comporte souvent des centaines de classes!
On ne peut pas les inclure une par une, c’est pourquoi PHP permet de faire de «l’auto-loading», comprenez du chargement automatique.
Ce chargement automatique s’effectue grâce à la fonction: spl_autoload_register('nom_de_la_fonction')
qui va s'exécuter dès que l’on essaiera d’instancier (de créer un objet) une classe qui n’a pas encore été déclarée avec require.
Pour inclure automatiquement des classes non déclarées :
<?php
function chargerClasse($classe) {
require $classe . '.php'; // On inclut la classe correspondante au paramètre passé.
}
spl_autoload_register('chargerClasse'); // On enregistre la fonction en autoload pour qu'elle soit appelée dès qu'on instanciera une classe non déclarée.
$perso = new Personnage;
?>
class.new.static.::$this fait référence à l'objet en cours, tandis que self fait référence à la classe en cours.Exemple d'éléments statiques:
<?php
class Personnage
{
private static $texteADire = 'Bonjour !';
public static function parler()
{
echo self::$texteADire;
}
}
echo Personnage::$texteADire; // Affiche 'Bonjour !'
Personnage::parler(); // Affiche 'Bonjour !'
?>
<?php
class Personnage
{
private static $compteur = 0;
public function __construct() {
self::$compteur++;
}
public static function getCompteur() {
return self::$compteur;
}
}
$perso1 = new Personnage;
$perso2 = new Personnage;
$perso3 = new Personnage;
echo Personnage::getCompteur(); // Affiche 3
?>
const.:: (comme pour les éléments statiques).Voici un code muet:
$perso = new Personnage(50);
Dans notre projet, on va considérer que le paramètre force ne peut prendre que 3 valeurs distinctes lorsque l’on crée un Personnage:
<?php
class Personnage
{
const FORCE_PETITE = 20;
const FORCE_MOYENNE = 50;
const FORCE_GRANDE = 80;
private $force;
public function __construct($force)
{
if (in_array($force, [self::FORCE_PETITE, self::FORCE_MOYENNE, self::FORCE_GRANDE]))
{
$this->force = $force;
}
}
}
$perso = new Personnage(Personnage::FORCE_MOYENNE);
?>
-> permet d'accéder à un élément d'un objet, tandis que :: permet d'accéder à un élément de la classe.$this, et à la classe en cours avec self.<?php
class Personnage
{
protected $force;
protected $localisation;
protected $experience;
protected $degats;
public function __construct($force, $degats)
{
$this->setForce($force);
$this->setDegats($degats);
$this->experience = 1;
}
public function frapper(Personnage $persoAFrapper)
{
$persoAFrapper->recevoirDegats($this->force);
}
public function gagnerExperience()
{
$this->experience++;
}
}
?>
class Magicien extends Personnage
{
private $magie;
public function lancerUnSort(Personnage $perso)
{
$perso->recevoirDegats($this->magie);
}
public function gagnerExperience()
{
// On appelle la méthode gagnerExperience de la classe parente
parent::gagnerExperience();
if ($this->magie < 100)
{
$this->magie += 10;
}
}
}
?>
extends.public : accessible de n'importe où.private : accessible uniquement depuis la classe.protected : accessible depuis la classe et les classes filles.abstract.Personnage, et des classes filles Guerrier, Magicien, etc.
Cela garantie que l'on ne créera jamais d'objet Personnage
<?php
abstract class Personnage
{
}
class Guerrier extends Personnage
{
}
$guerrier = new Guerrier; // OK
$perso = new Personnage; // Erreur fatale
?>
abstract.attaquer dans la classe abstraite Personnage.
Les classes filles Guerrier, Magicien devront redéfinir cette méthode.
<?php
abstract class Personnage
{
abstract public function attaquer();
}
class Guerrier extends Personnage
{
public function attaquer()
{
// Code de l'attaque
}
}
?>
On peut empêcher la redéfinition d'une méthode ou d'une classe.
final.
gagnerExperience dans la classe Personnage.<?php
class Personnage
{
final public function gagnerExperience()
{
// Code de l'expérience
}
}
class Guerrier extends Personnage
{
public function gagnerExperience() // Erreur fatale
{
// Code de l'expérience
}
}
?>
public et protected).extends pour hériter d'une classe.abstract.abstract.final.