Object Georiënteerd Programmeren: De Basisconcepten (PHP 8)

Dit overzicht bespreekt de kernprincipes van OOP met een eenvoudige uitleg en een codevoorbeeld in PHP 8.

  1. Class en Object

    Eenvoudige Beschrijving: Een Class is het algemene plan of de blauwdruk. Het definieert wat voor soort attributen (eigenschappen) en methods (handelingen) een ding zal hebben. Een Object is een tastbaar exemplaar van die blauwdruk. Je maakt een object met het trefwoord new.

    <?php
    class Auto {
        public function __construct(private string $kleur) {}
    
        public function rijden(): string {
            return "De {$this->kleur}e auto rijdt.";
        }
    }
    
    $mijnAuto = new Auto("rood");
    echo $mijnAuto->rijden(); // Output: De rode auto rijdt.
    ?>
  2. Attribuut en Method

    Eenvoudige Beschrijving: Een Attribuut is een eigenschap of kenmerk van een object (bijvoorbeeld kleur of naam). Een Method is een actie of handeling die het object kan uitvoeren (bijvoorbeeld starten of stoppen).

    <?php
    class Lamp {
        private bool $isAan = false; // Attribuut: toestand van de lamp
    
        public function zetAan(): void {
            $this->isAan = true;
        }
    
        public function getStatus(): string {
            return $this->isAan ? 'Aan' : 'Uit';
        }
    }
    
    $halLamp = new Lamp();
    $halLamp->zetAan();
    echo $halLamp->getStatus(); // Output: Aan
    ?>

    Uitbreiding : De waarde van een attributen kan je (vanaf php 8.4) uitlezen en wijzigen op 2 manieren : getter/setter-methods (zoals het voorbeeld hierboven) of property hooks ( get en set sleutelwoorden).

    <?php
    class Thermometer
    {
        // Private backing property
        private float $temperatuur = 0.0;
    
        public float $celsius {
            // Get‑hook — wordt uitgevoerd bij lezen
            get {
                echo "--> Getter uitgevoerd: waarde wordt gelezen.\n";
                return $this->temperatuur;
            }
            // Set‑hook — wordt uitgevoerd bij schrijven
            set (float $value) {
                if ($value < -273.0) {
                    echo "Fout: Temperatuur kan niet onder het absolute nulpunt komen.\n";
                    return;
                }
                echo "--> Setter uitgevoerd: waarde wordt gevalideerd en gewijzigd.\n";
                $this->temperatuur = $value;
            }
        }
    
        public float $fahrenheit {
            // Alleen een get‑hook — deze property wordt berekend op basis van $temperatuur
            get => ($this->temperatuur * 9/5) + 32;
        }
    }
    
    // Voorbeeldgebruik
    $mijnThermometer = new Thermometer();
    
    // Gebruik als normale property (roept de set hook op)
    $mijnThermometer->celsius = 20.0;
    
    // Gebruik als normale property (roept de get hook op)
    echo "De temperatuur is nu " . $mijnThermometer->celsius . "°C.\n";
    
    // Berekende property
    echo "Dat is " . $mijnThermometer->fahrenheit . "°F.\n";
    
    // Test validatie: deze zal niet worden geaccepteerd
    $mijnThermometer->celsius = -300.0;           
    ?> 
  3. Encapsulation (Inkapseling)

    Eenvoudige Beschrijving: Encapsulation zorgt dat de interne data van een object beschermd wordt. Dit betekent dat je niet zomaar de attributen van een object van buitenaf kunt wijzigen. In PHP doe je dit door de visibiliteit van attributen te beperken met private of protected en gecontroleerde toegang te geven via methods (getters en setters). Wens je geen beperking van de zichtbaarheid dan gebruik je public.

    <?php
    class KlantAccount {
        private int $saldo = 0; // Private Attribuut
    
        public function stort(int $bedrag): void {
            if ($bedrag > 0) {
                $this->saldo += $bedrag;
            }
        }
    
        public function getSaldo(): int {
            return $this->saldo;
        }
    }
    
    $account = new KlantAccount();
    $account->stort(200);
    echo $account->getSaldo(); // Output: 200
    ?>

    Bekijk het voorbeeld hieronder voor wat extra uitleg over protected

    <?php
    class KlantAccount {
        private int $saldo = 0;      // Private attribuut: alleen toegankelijk binnen deze class
        protected int $bonus = 0;    // Protected attribuut: toegankelijk binnen deze class en subclasses
    
        // Methode om geld te storten
        public function stort(int $bedrag): void {
            if ($bedrag > 0) {
                $this->saldo += $bedrag;
                // Bonus verhogen bij storting
                $this->bonus += intval($bedrag * 0.05); // 5% bonus
            }
        }
    
        // Getter voor saldo
        public function getSaldo(): int {
            return $this->saldo;
        }
    
        // Getter voor bonus
        public function getBonus(): int {
            return $this->bonus;
        }
    }
    
    // Subclass die protected attribuut kan gebruiken
    class PremiumKlantAccount extends KlantAccount {
    
        public function gebruikBonus(int $bedrag): void {
            if ($bedrag <= $this->bonus) {
                echo "Bonus gebruikt: {$bedrag}\n";
                $this->bonus -= $bedrag;
                $this->stort($bedrag); // bedrag toevoegen aan saldo
            } else {
                echo "Niet genoeg bonus beschikbaar.\n";
            }
        }
    
        public function toonBonus(): void {
            echo "Huidige bonus: {$this->bonus}\n";
        }
    }
    
    // Voorbeeldgebruik
    $account = new KlantAccount();
    $account->stort(200);
    echo "Saldo normaal account: " . $account->getSaldo() . "\n"; // 200
    echo "Bonus normaal account: " . $account->getBonus() . "\n"; // 10
    
    $premium = new PremiumKlantAccount();
    $premium->stort(500);
    echo "Saldo premium account: " . $premium->getSaldo() . "\n"; // 500
    $premium->toonBonus(); // 25
    $premium->gebruikBonus(20);
    echo "Saldo premium na bonus: " . $premium->getSaldo() . "\n"; // 520
    $premium->toonBonus(); // 5
    
    // $premium->bonus = 100; // FOUT: protected, kan niet van buitenaf worden aangepast
    ?>
    
  4. Constructor

    Eenvoudige Beschrijving: De constructor is de speciale method (__construct()) die automatisch wordt uitgevoerd wanneer een object wordt aangemaakt (met new). Het wordt gebruikt om de beginwaarden (attributen) van het nieuwe object in te stellen.

    <?php
    class Product {
        public function __construct(private string $naam) {
            echo "Product {$this->naam} is aangemaakt.";
        }
    
        public function getNaam(): string {
            return $this->naam;
        }
    }
    
    $melk = new Product("Melk");
    ?>
  5. Composition (Compositie)

    Eenvoudige Beschrijving: Composition is de "heeft een" relatie tussen classes. Een class gebruikt een object van een andere class als een van zijn eigen attributen. Bijvoorbeeld: een auto heeft een motor.

    <?php
    class Motor {
        public function start(): string {
            return "Motor gestart.";
        }
    }
    
    class AutoMetMotor {
        private Motor $motor;
    
        public function __construct() {
            $this->motor = new Motor();
        }
    
        public function rij(): string {
            return "Auto rijdt. " . $this->motor->start();
        }
    }
    
    $mijnWagen = new AutoMetMotor();
    echo $mijnWagen->rij(); // Output: Auto rijdt. Motor gestart.
    ?>
  6. Inheritance (Overerving)

    Eenvoudige Beschrijving: Inheritance is de "is een" relatie. Een nieuwe class (Derived Class) neemt alle attributen en methods van een bestaande class (Base Class) over met het woord extends. Dit bevordert herbruikbaarheid.

    <?php
    
    class Vervoermiddel   // Base Class (superclass)
    {
        public function verplaats(): string
        {
            return "Het middel beweegt.";
        }
    }
    
    class Fiets extends Vervoermiddel   // Derived Class (subclass)
    {
        public function bel(): string
        {
            return "Ring ring!";
        }
    }
    
    $stadsfiets = new Fiets();
    
    echo $stadsfiets->verplaats(); // Geërfde method
    echo $stadsfiets->bel();       // Eigen method
    
    // Output:
    // Het middel beweegt.
    // Ring ring!
    ?>

    De constructor van de Base Class roep je aan met parent::__construct():

    <?php
    class Vervoermiddel {
        protected string $merk;
        protected int $maxSnelheid;
    
        public function __construct(string $merk = '', int $maxSnelheid = 0) {
            $this->merk = $merk;
            $this->maxSnelheid = $maxSnelheid;
        }
    
        public function verplaats(): string {
            return "Het middel beweegt.";
        }
    }
    
    class Fiets extends Vervoermiddel {
        private int $aantalVersnellingen;
    
        public function __construct(string $merk, int $maxSnelheid, int $aantalVersnellingen) {
            parent::__construct($merk, $maxSnelheid);
            $this->aantalVersnellingen = $aantalVersnellingen;
        }
    
        public function bel(): string {
            return "Ring ring!";
        }
    
        public function getInfo(): string {
            return "Dit is een " . static::class . " van merk {$this->merk}. Aantal versnellingen: {$this->aantalVersnellingen}.";
        }
    }
    
    $stadsfiets = new Fiets("Gazelle", 35, 7);
    echo $stadsfiets->verplaats();
    echo $stadsfiets->bel();
    echo $stadsfiets->getInfo();
    ?>
  7. Method Overriding (Method Overschrijven)

    Eenvoudige Beschrijving: Dit is het aanpassen van een geërfde method in de Derived Class. U geeft de method een andere of uitgebreide functionaliteit. U kunt de oorspronkelijke method van de Base Class oproepen binnen de nieuwe method met parent::__construct().

    <?php
    class Dier {
        public function geluid(): string {
            return "Maakt een basisgeluid.";
        }
    }
    
    class Kat extends Dier {
        public function geluid(): string {
            return parent::geluid() . " Maar de Kat zegt 'Miau'.";
        }
    }
    
    $poes = new Kat();
    echo $poes->geluid();
    ?>
  8. Polymorfisme

    Eenvoudige Beschrijving: Polymorfisme betekent "vele vormen". Het verwijst naar het feit dat eenzelfde method (met dezelfde naam) in verschillende classes bestaat, maar telkens een andere actie uitvoert. Dit is handig wanneer je objecten van verschillende types in een lijst behandelt.

    <?php
    class Figuur {
        public function teken(): string {
            return "Een figuur wordt getekend.";
        }
    }
    
    class Cirkel extends Figuur {
        public function teken(): string {
            return "Een ronde vorm wordt getekend.";
        }
    }
    
    class Vierkant extends Figuur {
        public function teken(): string {
            return "Een vierkant met rechte hoeken wordt getekend.";
        }
    }
    
    $objecten = [new Cirkel(), new Vierkant()];
    foreach ($objecten as $obj) {
        echo $obj->teken();
    }
    ?>
  9. Static

    Eenvoudige Beschrijving: Static attributen of methods zijn Class-eigenschappen, en dus geen object-eigenschappen. Alle objecten delen dezelfde static waarde. Je roept een static method aan via de naam van de Class, niet via een object.

    <?php
    class Teller {
        private static int $gemaakteObjecten = 0;
    
        public function __construct() {
            self::$gemaakteObjecten++;
        }
    
        public static function getTotaalAantalTellers(): int {
            return self::$gemaakteObjecten;
        }
    }
    
    $item1 = new Teller();
    $item2 = new Teller();
    
    echo Teller::getTotaalAantalTellers(); // Output: 2
    ?>