PHP 5 added support for classes and interfaces. This made object-oriented code possible with one feature being polymorphism. That means you can call the same method on other objects and each object responds in its own way.
Table of Content
You will learn how polymorphism works in PHP with examples. Let’s get started.
Understand Polymorphism in PHP
Polymorphism lets you use the same method name on different objects.
Each object runs its own version of that method.
You work with shared rules but keep unique behavior.
Key points about polymorphism in PHP:
- You give different classes the same function name.
- Each class runs its own version of that method.
- You use interfaces or parent classes to set the rule.
- You can add new types without a code update.
Here is an example:
interface Message {
public function send();
}
class Email implements Message {
public function send() {
echo "Send email to [email protected]";
}
}
class SMS implements Message {
public function send() {
echo "Send SMS to +27831234567";
}
}
function deliverMessage(Message $message) {
$message->send();
}
deliverMessage(new Email());
echo "\n";
deliverMessage(new SMS());
Output:
Send email to [email protected]
Send SMS to +27831234567
- You use one method:
send()
. - Each class handles it in its own way.
- You add new message types without changing old code.
How to Implement Polymorphism in PHP
You can use inheritance to override methods or interfaces to define a common contract. This allows different objects to respond to the same method call in their own way.
Let’s see each one with examples.
PHP Polymorphism Through Inheritance
This example uses a base class called Tool
and two child classes: Hammer
and Wrench
. Each one overrides the use
method.
class Tool {
public function use() {
echo "Use a generic tool\n";
}
}
class Hammer extends Tool {
public function use() {
echo "Hammer a nail\n";
}
}
class Wrench extends Tool {
public function use() {
echo "Tighten a bolt\n";
}
}
function operateTool(Tool $tool) {
$tool->use();
}
operateTool(new Hammer()); // Hammer a nail
operateTool(new Wrench()); // Tighten a bolt
Polymorphism with Interfaces
Here, we define a Notifier
interface. Each class sends a message in a different way.
interface Notifier {
public function send($message);
}
class EmailNotifier implements Notifier {
public function send($message) {
echo "Send email: $message\n";
}
}
class SMSNotifier implements Notifier {
public function send($message) {
echo "Send SMS: $message\n";
}
}
function notifyUser(Notifier $notifier, $text) {
$notifier->send($text);
}
notifyUser(new EmailNotifier(), "Your order shipped.");
notifyUser(new SMSNotifier(), "Pickup ready.");
Polymorphism with Abstract Classes
Now we use an abstract class called Sensor
. Each sensor must define how it reads data, but they can share a pattern.
abstract class Sensor {
public function check() {
echo "Check sensor...\n";
$this->read();
}
abstract protected function read();
}
class TemperatureSensor extends Sensor {
protected function read() {
echo "Temperature: 21°C\n";
}
}
class PressureSensor extends Sensor {
protected function read() {
echo "Pressure: 101 kPa\n";
}
}
function runSensor(Sensor $sensor) {
$sensor->check();
}
runSensor(new TemperatureSensor());
runSensor(new PressureSensor());
Differences Between Abstract Classes and Interfaces in Polymorphism
You use the abstract class when classes share code. You want to enforce some methods but also give default behavior.
While the interface when you care about method names. You do not provide any shared code. Just set rules for what a class must include.
Here are the differences between them:
Method Implementation:
You can include both defined and abstract methods. You can mix shared code and required code with abstract class.
But in the interface, you cannot include any method code. Every method in an interface is public and must be implemented fully.
Multiple Inheritance:
A class can extend only one abstract class while the interface, A class can implement many interfaces at once.
Properties:
You can define properties (like $name
or $type
) and set default values with the abstract class. But you can not have properties. You only define method names in the interface.
Constructor Support:
An abstract class can have a constructor. You can set up logic that all child classes inherit. But in the interface, you cannot have a constructor. You leave the setup to each class.
Use Example:
Here is an example of an abstract class:
abstract class Sensor {
public function check() {
echo "Checking...\n";
$this->read();
}
abstract protected function read();
}
When different sensors share setup code but each one reads data differently.
An example of the interface:
interface AlertSystem {
public function sendAlert($msg);
}
When different alert systems follow the same send method.
Here is a table that shows you the key differences:
Feature | Abstract Class | Interface |
---|---|---|
Method code allowed | Yes | No |
Properties allowed | Yes | No |
Constructor support | Yes | No |
Multiple inheritance | No | Yes |
Purpose | Shared behavior + rules | Rules only |
Examples
Game character abilities (within an abstract Class):
The abstract method forces subclasses to define their own logic while It shares base setups.
abstract class Character {
public function prepare() {
echo "Getting ready...\n";
$this->action();
}
abstract protected function action();
}
class Archer extends Character {
protected function action() {
echo "Shoots an arrow\n";
}
}
class Mage extends Character {
protected function action() {
echo "Casts a spell\n";
}
}
function perform(Character $c) {
$c->prepare();
}
perform(new Archer()); // Shoots an arrow
perform(new Mage()); // Casts a spell
You get one place for common steps (prepare()
), but you let each character define how it acts.
Device controller (mix of interface and polymorphism):
One interface, many devices, and one control function that works with all.
interface Device {
public function activate();
}
class Fan implements Device {
public function activate() {
echo "Fan spinning\n";
}
}
class Light implements Device {
public function activate() {
echo "Light turned on\n";
}
}
class Heater implements Device {
public function activate() {
echo "Heating room\n";
}
}
function control(Device $device) {
$device->activate();
}
control(new Fan()); // Fan spinning
control(new Light()); // Light turned on
control(new Heater()); // Heating room
You can control any device without changing your logic. This helps you swap in new devices later.
Alert System (Using an Interface):
Interface-based polymorphism. No shared parent class.
interface AlertSystem {
public function send($message);
}
class EmailAlert implements AlertSystem {
public function send($message) {
echo "Email: $message\n";
}
}
class RadioAlert implements AlertSystem {
public function send($message) {
echo "Radio broadcast: $message\n";
}
}
function issueAlert(AlertSystem $system, $text) {
$system->send($text);
}
issueAlert(new EmailAlert(), "Storm coming");
issueAlert(new RadioAlert(), "Power outage");
You do not need inheritance. Each alert class only needs to follow the same contract (send
method). This is cleaner when the classes have nothing in common except behavior.
Wrapping Up
You learned how polymorphism works in PHP and how it allows you to call the same method on different objects, where each object responds in its own way.
Here is a quick recap:
- Polymorphism lets you define the same method name across different classes. It allows each class to implement it in its own unique way.
- Inheritance lets a child class override methods of a parent class. This keeps shared functionality.
- Interfaces define a contract for classes. It ensures they all implement the same methods but with their own behavior.
- Abstract classes provide a base with shared functionality but force child classes to define their own implementation for abstract methods.