Le PHP objet§

L’objet§

Classes et objets§

Les objets sont des structures de données contenant des variables (appelées attributs) et des fonctions (appelées méthodes).

Les classes sont la définition, le modèle, le “moule” qui permet de fabriquer des objets.

Pourquoi le PHP objet§

  • Permet de bénéficier des avantages de la programmation objet en PHP
    • meilleure lisibilité
    • programmation plus naturelle
    • meilleure réutilisabilité du code
  • Notation PEAR

Syntaxe de classe basique§

Mot clé : class

<?php
class Personne
{
}
?>

Propriété, méthodes et constructeur§

  • Portée (visibilité) :

    • Principe d’encapsulation
    • public, protected, private
    <?php
    class Personne
    {
      private $_prenom;
      private $_nom;
      private $_age;
    
      // Constructeur
      public function __construct($prenom, $nom)
      {
          $this->_prenom = $prenom;
          $this->_nom = $nom;
      }
    
      public function sePresenter()
      {
          echo 'Bonjour ! Je m\'appelle '.$this->_prenom.' '.$this->_nom;
      }
    }
    ?>
    

Instances (objets)§

  • Création d’un objet de la classe avec mot clé new
  • Appelle méthode (et propriété) avec ->
  • Accès à l’instance explicite avec $this
<?php
class Personne
{
    ...
}

$tom = new Personne('Tom', 'Doyen');
$tom->sePresenter();
?>

Méthodes magiques§

  • Méthodes réservées (magiques) surchargeables
    • __construct() : Constructeur
    • __toString() : Cast implicite vers chaîne de caractère (exemple : echo $tom;)
    • __set() et __get() : surcharge de l’accès aux propriété privées (à éviter, préférer des accesseurs explicites)
    • __clone() : surcharge comportement méthode copie mémoire $obj->clone() (équivalent contructeur par copie du C++)
    • (Méthodes magiques)

Héritage§

Définit un cas particulier d’une classe. Par exemple, un Etudiant est une Personne, avec des choses en plus.

<?php
class Personne
{
    ...
}
class Etudiant extends Personne // Un Etudiant est un cas particulier de Personne
{
    private $_num_etudiant; // qui a en plus un numéro étudiant

    public function __construct($prenom, $nom, $num_etudiant)
    {
        parent::__construct($prenom, $nom); // appel du constructeur de la classe Personne
        $this->_num_etudiant = $num_etudiant; // puis initialisation des attributs spécifiques
    }

    public function sePresenter() // redéfinit la méthode de la classe Personne
    {
        parent::sePresenter(); // appel de la méthode de la classe Personne (sans cette ligne la redéfinition est totale)
        echo 'Et mon numéro étudiant est '.$this->_num_etudiant;
    }
}
?>

Contrainte de typage§

  • Contraintes de typage des paramètres d’une fonction

    <?php
    function faireParler(Personne $p)
    {
        // on sait que $p est une Personne, donc cette ligne va marcher
        $p->sePresenter();
    
        // $p est peut être une classe fille, un Etudiant par exemple !
        // ce n'est pas gênant, un Etudiant EST une Personne et sait donc se présenter.
    }
    
    $tom = new Etudiant('Tom', 'Doyen', 'p12345678');
    faireParler($tom); // À votre avis, est-ce que c'est sePresenter de Personne ou d'Etudiant qui sera appelé ?
    ?>
    

Méthode statiques§

  • Méthode de la classe indépendante de l’instance
  • Mot clé static
  • Peut être appelée par l’opérateur de résolution de portée ::
  • À éviter la plupart du temps. S’il y en a besoin, c’est souvent un problème de design.
<?php
class a
{
  public static function parler()
  {
    echo 'Hello World';
  }
}

a::parler();
?>

Attributs statiques§

  • Mot clé static
  • Accès depuis extérieur avec ::
  • Accès depuis méthode statique avec self
  • À éviter la plupart du temps. Ce sont des variables globales déguisées. S’il y en a besoin, c’est souvent un problème de design.
<?php
class a
{
  private static $compteur = 0;
  private $mon_numero;

  public function __construct()
  {
      self::$compteur++;
      $this->mon_numero = self::$compteur;
  }

  public static function parler()
  {
    echo 'Je suis le '.$this->mon_numero.'eme (sur '.self::$compteur.' au total)';
  }
}
?>

Classes et méthodes abstraites§

  • Regroupent des comportements communs
  • Mais représentent un objet abstrait
  • N’ont donc pas d’existence propre
<?php
abstract class Vehicule
{
    private $numeroDeSerie;
    public function getNumeroDeSerie() { return $this->numeroDeSerie; }
    public abstract function seDeplacer();
}
class Voiture extends Vehicule
{
    private ...
    public function seDeplacer()
    {
        $this->pedaleAccelerateur->appuyer();
    }
}
class Moto extends Vehicule
{
    private ...
    public function seDeplacer()
    {
        $this->poignee->tourner();
    }
}
?>

À quoi ça sert ?

  • Regroupe des informations communes (numéro de série) dans la classe mère, évite le copier/coller de code
  • Déclare un comportement (seDeplacer) qui est garanti être appelable sur tous les véhicules
    • encapsulation + polymorphisme : quelqu’un qui a un Vehicule sait qu’il peut se déplacer, sans forcément savoir comment

Interfaces§

  • Peut se voir comme une classe 100% abstraite
  • Ne définit que des comportements
  • Mot clé interface pour définir des fonctions à implémenter pour une classe (méthodes publiques seulement)
  • implements pour lier une classe à une interface
<?php
interface SaitParler
{
  public function parler();
}

class Personne implements SaitParler
{
  public function parler()
  {
    echo 'Hello World';
  }
}

class Robot implements SaitParler
{
  public function parler()
  {
    echo '10100110100';
  }
}
?>

À quoi ça sert ?

  • Déclare un comportement (saitParler) qui est garanti être appelable par tous ceux qui implémentent SaitParler

    • Mais on peut implémenter plusieurs interfaces en même temps (implements Int1, Int2, Int3), alors qu’on ne peut étendre que d’une classe
    • Il est également possible pour une fonction de prendre en paramètre un objet qui implémente une interface :
    <?php
    function faireParler(SaitParler $sp)
    {
        echo 'Tu vas parler, ordure ?';
        $sp->parler();
    }
    ?>
    
    • Exemples “real-world” :
      • Serializable (“représentable comme du texte”, pour sauvegarder dans un fichier
      • Cloneable
      • ArrayAccess (pour avoir le droit d’utiliser les crochet [] sur nos propres classes, hé oui on peut créer nos propres tableaux et les utiliser de façon transparente)
      • Iterator (pour avoir le droit d’utiliser la structure foreach sur nos propres classes)

Exercice§

  • Réorganisez votre code en orienté objet
    • une classe “Connection” pour gérer la connexion avec la BD
    • une classe “Film” (dont les instances pourront être stockées dans un tableau par exemple)
    • une classe “Acteur” (dont les instances pourront être stockées dans un tableau par exemple)
    • etc...