PHP: Polymorphism

Polymorphism is the ability of a property, a method or an object to take many forms. It is derived from the Greek word πολύς (polys), meaning “many, much” and μορφή (morphē) meaning “form, shape”.

We have seen a kind of polymorphism in our first tutorial on object-oriented programming, inside the section Object Inheritance: Subclasses, where a class method is redefined to print a different string in the inheriting class. This is known as method overriding, a kind of polymorphism, where an inherited method behave as implemented in a derived class, which is different from its original behaviour in the base class. We go through method overriding again here, but with a different example.

Method Overriding

We declare a class called Country which has the method getCurrency(), which prints an empty string. This class will be extended by classes bearing country names and the method getCurrency() will be overidden in the inheriting class to print respective currencies. This is one form of polymorphism.

					
						class Country {
							function getCurrency() {
								echo '';
							}
						}
					
				

Next we create two subclasses, Bhutan and Myanmar, of the class Country. The currency of Bhutan is known as Bhutanese Ngultrum and the currency of Myanmar is known as Burmese Kyat. We override the getCurrency() method in the extended classes to return these currencies.

php polymorphism
					
						class Country {
							function getCurrency() {
								echo '';
							}
						}

						class Bhutan extends Country {
							function getCurrency() {
								echo 'Ngultrum' . PHP_EOL;
							}
						}

						class Myanmar extends Country {
							function getCurrency() {
								echo 'Kyat' . PHP_EOL;
							}
						}

						function printCurrency($obj) {
							if ($obj instanceof Country) {
								$obj->getCurrency();
							} else {
								echo "Error: Passed a different kind of object" . PHP_EOL;
							}					
						}

						$bhutan = new Bhutan();
						printCurrency($bhutan);

						$myanmar = new Myanmar();
						printCurrency($myanmar);
					
				

Method Overloading

Now those with C++ background might be aware of the fact that in C++ there can exist two or more functions with the same name, but with different type and/or number of parameters. This is known as function overloading.

PHP does not support method overloading directly. For example, if you try to pass extra parameters to the getCurrency() method (above), it will throw a warning. Say you pass an argument $x (supposedly an exchange rate) to it as shown below:

					
						class Country {
							function getCurrency() {
								echo '';
							}
						}

						class Bhutan extends Country {
							function getCurrency($x) {
								echo 'Ngultrum' . PHP_EOL;
							}
						}
					
				

It will throw the following warning message:

					
						Warning: Declaration of Bhutan::getCurrency($x) should be compatible with 
						¬ Country::getCurrency()
					
				

For the purpose of overloading, there exist special functions in PHP like __call() and __callStatic() classified as magic methods. We will learn about them in detail in a separate page.

Abstract Methods & Interfaces

Some methods, like the getCurrency() method (above), makes sense only when implementation is done in the inheriting classes. PHP allows you to have such methods exactly by declaring them as abstract, without the need of a function body. Which means we could have declared our getCurrency() method inside the Country class without the body as below:

					
						abstract function getCurrency();
					
				

Or you can have a whole class loaded with such kind of "abstract" functions and constants to be implemented in the inheriting classes. Classes as such which contain only function prototypes (unimplemented) are known as interfaces.

We will explore both abstract classes and interfaces separately in detail.

Notes

  • Abstract classes cannot be instantiated (so no use of new); they can only be inherited.
  • PHP does not support multiple inheritance as in C++; it instead provides interfaces.