Polymorphism, Abstract Classes, and Interfaces in PHP

Multithreaded JavaScript, O'Reilly 2021, is available for early access and pre-order!

This article will demonstrate Abstract Classes, Interfaces, and Polymorphism, as implemented in the PHP5 language, which isn't as versatile as other languages I've worked with (such as C++).

Interfaces

An Interface is kind of like a class, although you can't use it directly, classes must implement them. Think of it as a prototype or a blueprint of a class. In your interface you will declare the functions, but they won't actually have any code inside of them. You also aren't allowed to define your data storage.

In the classes that you implement your interface in, you must use all of the defined functions of the interface, otherwise you'll get a PHP error. This is because our program which will interact with the implemented classes expect our class to be able to communicate in the methods that we define here. This way, as we modify functionality elsewhere in the application, or add extra functionality in our implementing classes, we don't break backwards compatibility.

Abstract Classes

An abstract class is like a normal class, except that you cannot instantiate them, you must extend them first then instantiate. Your abstract classes can have data members and function calls (and their functionality).

Polymorphism

When we start to extend classes, and add functionality to them which wasn't there previously, and even override existing methods (functions), this is called polymorphism. Here's my example of this (not the best but it shows the basics):

<?php
interface Human {
 public function getName();
 public function setName($name);
}

abstract class Military {
 private $rank;

 public function __construct($rank) {
 $this->rank = $rank;
 }
 public function setRank($rank) {
 $this->rank = $rank;
 }
 public function getRank() {
 return $this->rank;
 }
}

class Soldier extends Military implements Human {
 private $name;

 public function __construct($name, $rank) {
 $this->name = $name;
 parent::__construct($rank); # parent::setName($rank);
 }
 public function setName($name) {
 $this->name = $name;
 }
 public function getName() {
 return "My name is: " . $this->name . "<br />n";
 }
 public function getRank() {
 return "My rank is: " . parent::getRank() . "<br />n";;
 }
 public function getFull() {
 return "I am " . parent::getRank() . " {$this->name}<br />n";
 }
}

$goodSoldier = New Soldier('Thomas', 'Officer');

echo $goodSoldier->getName();
echo $goodSoldier->getRank();
echo $goodSoldier->getFull();
echo "<br />n";
$goodSoldier->setRank('Colonel');
$goodSoldier->setName('Mustard');
echo $goodSoldier->getName();
echo $goodSoldier->getRank();
echo $goodSoldier->getFull();

The output of our code is the following:

My name is: Thomas
My rank is: Officer
I am Officer Thomas

My name is: Mustard
My rank is: Colonel
I am Colonel Mustard

Also, funny trivia, the double colon character (::) is referred to by its Hebrew name, “Paamayim Nekudotayim”.

Tags: #php
Thomas Hunter II Avatar

Thomas has contributed to dozens of enterprise Node.js services and has worked for a company dedicated to securing Node.js. He has spoken at several conferences on Node.js and JavaScript, is an O'Reilly published author, and is an organizer of NodeSchool SF.