OOP Mastery (POO)
Thème :
Junior
3 vues ·6/17 leçons

Les Classes Abstraites

Les classes abstraites fournissent une implémentation partielle tout en obligeant les sous-classes à implémenter des méthodes spécifiques.

Classe Abstraite de Base

<?php
abstract class Shape {
    public function __construct(
        protected string $color
    ) {}

    // Méthode abstraite - DOIT être implémentée
    abstract public function getArea(): float;

    // Méthode concrète - héritée telle quelle
    public function getColor(): string {
        return $this->color;
    }

    // Méthode concrète utilisant la méthode abstraite
    public function describe(): string {
        return "Une forme {$this->color} d'aire " . $this->getArea();
    }
}

class Rectangle extends Shape {
    public function __construct(
        string $color,
        private float $width,
        private float $height
    ) {
        parent::__construct($color);
    }

    public function getArea(): float {
        return $this->width * $this->height;
    }
}

class Circle extends Shape {
    public function __construct(
        string $color,
        private float $radius
    ) {
        parent::__construct($color);
    }

    public function getArea(): float {
        return pi() * $this->radius ** 2;
    }
}

Le Pattern Template Method (Méthode Modèle)

<?php
abstract class DataExporter {
    // Méthode modèle - définit l'algorithme
    final public function export(array $data): string {
        $this->validate($data);
        $formatted = $this->format($data);
        return $this->output($formatted);
    }

    // Étape concrète
    protected function validate(array $data): void {
        if (empty($data)) {
            throw new InvalidArgumentException('Les données ne peuvent pas être vides');
        }
    }

    // Étapes abstraites - les sous-classes DOIVENT les implémenter
    abstract protected function format(array $data): string;
    abstract protected function output(string $content): string;
}

class CsvExporter extends DataExporter {
    protected function format(array $data): string {
        $lines = [];
        foreach ($data as $row) {
            $lines[] = implode(',', $row);
        }
        return implode("\n", $lines);
    }

    protected function output(string $content): string {
        return $content;  // Retourner tel quel
    }
}

class JsonExporter extends DataExporter {
    protected function format(array $data): string {
        return json_encode($data, JSON_PRETTY_PRINT);
    }

    protected function output(string $content): string {
        return $content;
    }
}

Abstract VS Interface

Fonctionnalité Interface Classe Abstraite
Méthodes Seulement les signatures Abstraites et concrètes
Propriétés Constantes seulement N’importe quelles propriétés
Multiple Oui Non (héritage simple)
Constructeur Non Oui
Visibilité Publique uniquement Toute visibilité
Utiliser quand Définir un contrat Partager une implémentation

Quand Utiliser les Classes Abstraites ?

<?php
// Utiliser une classe abstraite quand :
// 1. Vous avez une implémentation partagée
// 2. Vous avez besoin de membres protégés
// 3. Vous voulez le pattern Template Method

abstract class Repository {
    public function __construct(
        protected PDO $pdo  // Dépendance partagée
    ) {}

    // Implémentation partagée
    protected function execute(string $sql, array $params = []): PDOStatement {
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($params);
        return $stmt;
    }

    // Les sous-classes définissent leur entité
    abstract protected function getTableName(): string;
    abstract protected function hydrate(array $row): object;
}

Exemple Concret

Un processeur de paiement abstrait avec le pattern Template Method

<?php
declare(strict_types=1);

// Processeur de paiement abstrait avec méthode modèle
abstract class PaymentProcessor {
    abstract protected function validatePayment(float $amount): void;
    abstract protected function processTransaction(float $amount): string;
    abstract protected function sendReceipt(string $transactionId): void;

    // Méthode modèle
    final public function processPayment(float $amount): string {
        $this->validatePayment($amount);
        $transactionId = $this->processTransaction($amount);
        $this->sendReceipt($transactionId);
        return $transactionId;
    }

    // Méthode hook - peut être surchargée
    protected function logTransaction(string $id): void {
        echo "Transaction enregistrée : $id\n";
    }
}

class StripeProcessor extends PaymentProcessor {
    protected function validatePayment(float $amount): void {
        if ($amount < 0.50) {
            throw new InvalidArgumentException('Montant minimum : 0,50 €');
        }
    }

    protected function processTransaction(float $amount): string {
        // Appel à l'API Stripe
        return 'stripe_' . bin2hex(random_bytes(8));
    }

    protected function sendReceipt(string $transactionId): void {
        echo "Reçu Stripe envoyé pour : $transactionId\n";
    }
}

$processor = new StripeProcessor();
$txId = $processor->processPayment(99.99);
?>

Les Grimoires


📘 Cette leçon fait partie du cours Maîtrise de la POO en PHP sur la plateforme d’apprentissage RostoDev.

Prêt à passer à la suite ?

Vous avez terminé cette leçon sur Les Classes Abstraites. Continuez votre apprentissage avec la prochaine leçon ou explorez d'autres formations.