🏠 Home / Hub

🐘 PHP Lesson 09 — Inheritance & Polymorphism

← Back to PHP Menu  |  🏠 Hub

1. extends — Inheritance

<?php

// Parent class
class Animal {
    public function __construct(
        protected string $name,
        protected string $sound
    ) {}

    public function speak(): string {
        return "{$this->name} says {$this->sound}!";
    }

    public function eat(string $food): string {
        return "{$this->name} is eating {$food}.";
    }

    public function __toString(): string {
        return "Animal({$this->name})";
    }
}

// Child class
class Dog extends Animal {
    public function __construct(string $name, private string $breed) {
        parent::__construct($name, "Woof");  // parent constructor ခေါ်ရမယ်
    }

    public function fetch(string $item): string {
        return "{$this->name} fetches the {$item}! 🐕";
    }

    public function getBreed(): string { return $this->breed; }
}

class Cat extends Animal {
    public function __construct(string $name, private bool $indoor = true) {
        parent::__construct($name, "Meow");
    }

    public function purr(): string {
        return "{$this->name} purrs... 😺";
    }
}

$dog = new Dog("Rex", "Labrador");
$cat = new Cat("Mimi");

echo $dog->speak();      // "Rex says Woof!" — inherited
echo $dog->eat("bone");  // "Rex is eating bone." — inherited
echo $dog->fetch("ball"); // "Rex fetches the ball! 🐕" — own method

echo $cat->speak();   // "Mimi says Meow!"
echo $cat->purr();    // "Mimi purrs... 😺"

// instanceof check
var_dump($dog instanceof Dog);    // true
var_dump($dog instanceof Animal); // true
var_dump($cat instanceof Dog);    // false

2. Method Overriding & parent::

<?php

class Shape {
    public function __construct(protected string $color = "black") {}

    public function area(): float { return 0.0; }

    public function describe(): string {
        return "A {$this->color} " . get_class($this) .
               " with area " . number_format($this->area(), 2);
    }
}

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

    // Override area()
    public function area(): float {
        return M_PI * $this->radius ** 2;
    }
}

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

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

    // Override + extend parent method
    public function describe(): string {
        $parentDesc = parent::describe();  // call parent's method
        return $parentDesc . " ({$this->width}x{$this->height})";
    }
}

$c = new Circle(5);
$r = new Rectangle(4, 6);

echo $c->describe();  // "A red Circle with area 78.54"
echo $r->describe();  // "A blue Rectangle with area 24.00 (4x6)"

3. Polymorphism

<?php

class Payment {
    public function __construct(protected float $amount) {}
    public function process(): string { return "Processing payment"; }
    public function getAmount(): float { return $this->amount; }
}

class CreditCard extends Payment {
    public function process(): string {
        $fee = $this->amount * 0.02;
        return sprintf("💳 Credit Card: $%.2f (fee: $%.2f)", $this->amount, $fee);
    }
}

class PayPal extends Payment {
    public function process(): string {
        $fee = $this->amount * 0.015;
        return sprintf("🔵 PayPal: $%.2f (fee: $%.2f)", $this->amount, $fee);
    }
}

class KPay extends Payment {
    public function process(): string {
        return sprintf("📱 KPay: $%.2f (no fee!)", $this->amount);
    }
}

// Polymorphism — same method call, different behavior
$payments = [
    new CreditCard(100),
    new PayPal(200),
    new KPay(150),
];

foreach ($payments as $payment) {
    echo $payment->process() . "\n";
    // Type hint accepts Payment or any subclass
}

// Type hinting with polymorphism
function processPayment(Payment $p): void {
    echo "Total: $" . $p->getAmount() . "\n";
    echo $p->process() . "\n";
}

processPayment(new CreditCard(500));
processPayment(new KPay(300));

4. Abstract Classes

<?php

// Abstract class = cannot be instantiated directly
// Force child classes to implement specific methods

abstract class Report {
    public function __construct(protected string $title) {}

    // Abstract method — MUST be implemented by children
    abstract public function generate(): string;
    abstract public function getFormat(): string;

    // Concrete method — children inherit as-is
    public function header(): string {
        return "=== {$this->title} ({$this->getFormat()}) ===";
    }

    // Template method pattern
    public function render(): string {
        return $this->header() . "\n" . $this->generate();
    }
}

class PDFReport extends Report {
    public function generate(): string {
        return "PDF content for: {$this->title}\n[PDF binary data...]";
    }

    public function getFormat(): string { return "PDF"; }
}

class HTMLReport extends Report {
    public function generate(): string {
        return "<html><body><h1>{$this->title}</h1></body></html>";
    }

    public function getFormat(): string { return "HTML"; }
}

class CSVReport extends Report {
    public function generate(): string {
        return "title,date\n\"{$this->title}\",\"" . date('Y-m-d') . "\"";
    }

    public function getFormat(): string { return "CSV"; }
}

// new Report("Test"); ❌ Fatal Error — cannot instantiate abstract class

$reports = [
    new PDFReport("Sales Report"),
    new HTMLReport("Monthly Summary"),
    new CSVReport("User Data"),
];

foreach ($reports as $report) {
    echo $report->render() . "\n\n";
}
⚠️ Abstract class မှာ abstract method တစ်ခုဆိုပြီးရင် class ကို abstract ဆိုရမယ်

5. final — Inheritance ပိတ်ခြင်း

<?php

// final class — cannot be extended
final class Singleton {
    private static ?self $instance = null;

    private function __construct(private string $config) {}

    public static function getInstance(): self {
        if (self::$instance === null) {
            self::$instance = new self("default");
        }
        return self::$instance;
    }

    public function getConfig(): string { return $this->config; }
}

// class ExtendedSingleton extends Singleton {} ❌ Fatal Error

// final method — cannot be overridden in child
class Base {
    public function normal(): string { return "can override"; }

    final public function locked(): string { return "cannot override!"; }
}

class Child extends Base {
    public function normal(): string { return "overridden OK"; }
    // public function locked(): string {} ❌ Fatal Error
}

📌 Inheritance Keywords

KeywordUsageDescription
extendsclass Dog extends AnimalInherit from parent
parent::parent::__construct()Call parent method
abstractabstract class / methodCannot instantiate, must implement
finalfinal class / methodCannot extend / override
instanceof$obj instanceof ClassType check (includes parents)
get_class()get_class($obj)Get actual class name
get_parent_class()get_parent_class($obj)Get parent class name

← PHP 08  |  Next: PHP 10 → Interfaces & Abstract →

📌 Study Checklist