Factorisation
Classes et méthodes abstraites
Une classe abstraite sert à définir un ensemble de propriétés et de méthodes, qui seront utilisables dans les classes filles. Cette classe ne peut être instanciée (on ne peut pas faire un new
).
L'intérêt est de regrouper des propriétés et méthodes communes, sans permettre d'instancier la classe. On ne peut par exemple pas faire un new Animal
dans l'exemple ci-dessous. Il faut instancier les classes filles à la place.
Une méthode abstraite peut être définie dans une classe abstraite. On écrit le mot-clé abstract
suivi de la signature de la fonction. Son but est de forcer l'implémentation de la méthode dans les classes filles (qui devront donner un corps à la méthode).
abstract class Animal
{
abstract public function call(): string;
}
class Dog extends Animal
{
// Pour étendre Animal, Dog DOIT avoir une méthode call() définie
public function call(): string
{
return 'Waf';
}
}
Interface
Une interface permet de forcer l'implémentation de certaines méthodes dans un objet. C'est un contrat, permettant d'assurer que certaines méthodes sont définies et implémentées dans une ou plusieurs classes.
⚠️ Une classe peut implémenter plusieurs interfaces.
⚠️ Une interface peut étendre une ou plusieurs interfaces.
interface Test
{
public function getTest();
}
class Foo implements Test, Test2, Test3
{
// Pour implémenter Test, Foo DOIT avoir une méthode getTest() définie
public function getTest()
{
return 'ok';
}
}
instanceof
Le mot-clé ìnstanceof
permet de vérifier si une variable est une instance d'une classe, d'une interface ou d'une de ses filles.
// Bar.php
class Bar {}
// Foo.php
class Foo extends Bar implements TestInterface {}
// Baz.php
class Baz implements TestInterface {}
// index.php
$foo = new Foo();
$bar = new Bar();
$baz = new Baz();
var_dump($foo instanceof Foo); // Bool (true)
var_dump($bar instanceof Bar); // Bool (true)
var_dump($foo instanceof Test); // Bool (false)
var_dump($baz instanceof TestInterface); // Bool (true)
var_dump($bar instanceof TestInterface); // Bool (false)
var_dump($foo instanceof TestInterface); // Bool (true)
Traits
Un trait fonctionne comme une classe et permet de regrouper des propriétés et des méthodes qui vont ête utilisées dans d'autres classes. Un trait ne peut pas être instancié. Il s'utilise avec use
(oui, encore !) pour inclure le code du trait dans une classe.
Pensez l'utilisation d'un trait comme un copier-coller dans une classe : vous prenez tout le contenu du trait et le collez là où l'appel est fait.
Un exemple de déclaration de trait, où on déclare une propriété et un getter :
trait TestTrait
{
private $test;
private function getTest()
{
// ...
}
}
Un exemple d'utilisation de ce trait dans une classe :
class Test
{
use TestTrait;
use TestTrait2;
// Ici, on peut utiliser $this->test et $this->getTest(),
// meme s'ils sont privés !
// Comme les éléments sont inclus, $this->test
// est déclaré privé dans la classe Test
}
Espaces de nom
Le nommage d'une classe (on parle de nom complet ou FQCN) ne se limite pas au seul nom de la classe. Le FQCN contient également l'espace de nom de la classe, c’est-à-dire un éventuel préfixe et le dossier où la classe se trouve. Ce FQCN se base sur un dossier (dans notre exemple classes
).
Imaginons l'organisation suivante :
classes/
| - Traits/
| - Truc/
| - TestTrait2.php
| - TestTrait.php
| - Foo.php
| - Bar.php
| - Baz.php
Si classes
est le dossier servant de base à nos classes PHP, les différentes classes auront (ou non) un namespace (espace de nom). Par exemple, Foo
, Bar
, Baz
n'auront pas de namespace (ils sont à la racine de nos classes), alors que TestTrait
et TestTrait2
auront un namespace, pour indiquer le dossier où il se trouve :
// classes/Traits/TestTrait.php
namespace Traits;
trait TestTrait
{
// ...
}
// classes/Traits/Truc/TestTrait2.php
namespace Traits\Truc;
trait TestTrait2
{
// ...
}
⚠️ La séparation des dossiers s'écrit avec un \
dans les namespaces
Exceptions et try/catch
En Php, et dans de nombreux autres langages orientés objet, une mécanique permet de gérer les erreurs : les exceptions. Il faut les comprendre comme "des cas non prévus" du programme et, lorsqu'une exception est levée (qu'une erreur se produit), le programme peut réagir en fonction.
Cela permet par exemple d'utiliser une connexion de secours si une première BdD ne répond pas, ou de réagir à n'importe quelle erreur prévue dans notre programme. Php propose déjà un objet Exception
, vous permettant d'en créer une et vous pouvez la lever avec le mot-clé throw
.
Une exception peut être attrapée, pour la traiter ou afficher le message d'erreur, avec le bloc try/catch :
function throwException() {
// Pour lever une exception, on utilise le mot-clé throw
throw new Exception('Ceci est une exception');
}
// On peut "tester" des instructions dans un bloc try
// Si une exception est levée dans ces instructions,
// on peut les attraper dans un ou des blocs catch
try {
throwException();
} catch(Exception $e) {
echo $e->getMessage();
}