Polymorphism

Published on Jun 23, 2011 by Pim Elshoff

Programming #OOP #Polymorphism #Inheritance #Concept #Definition #PHP

If inheritance can feed your kittens, polymorphism will solve world peace ánd become beauty queen to boot. Read all about it in this article!

Classical Greek monomorphOne of the cornerstones of software engineering with OOP is polymorphism. Polymorphism comes from the Greek polymorphismos and means ‘having multiple forms’. There are various concepts in Computer Science called polymorphism and in the context of OOP we are talking about subtyping polymorphism or dynamic polymorphism.

The idea of polymorphism is that you can use any instance of a subtype of a type, where an instance of that type can be used. We call code that ‘works with’ more than one specific type polymorph.

A special case of polymorhpism is the Liskov Substitution Principle. Your code adheres to the LSP if you can exchange types for any of their subtypes and still have an equally valid program. Or: if you can use an object of class Person, you must also be able to use an object of class Student, because a Student is a Person. Subtyping that follows the LSP is called strong behavioral subtyping.

What the LSP means in practice is what we have referred to in the past as ‘not breaking the contract’. Not breaking the contract means that:

  • the parameters the subtype expects are no more constrained than the parameters of the parent, or the preconditions of the child are not stronger than the preconditions of the parent
  • the return values the subtype produces are no less constrained than the return values of the parent, or the postconditions of the child are not weaker than the preconditions of the parent

For PHP, real design by contract does not seem to be possible, due to the fact that there is currently no library that enables validating postconditions.

Wow that was theoretical. Now let’s look at some practical stuff before finalizing the theory.

‘Is a’ relationships

We can think of polymorphism as a means of making sure that whatever object we want to call a method or property on: if it is an instance of the child we can treat it as an instance of the parent and so, if the parent has the method we can call the method.

For example, if you want to call method ‘echoName’ on an object, you need to make sure that it is capable of that method. You could do lame PHP checks, but the Cool OOP Way is to make sure that the object is of type Person, the class where we first introduced echoName. We use the instanceof keyword to check if our parameter is an instance of Person.

      public function echoThisObject($parameter)
      {
            if ($parameter instanceof Person)
            {
                  // We can safely call echoName now
                  $parameter->echoName();
            }
      }

Okay, this leaves room for some improvement. Really, we don’t want any $parameter value to not be a Person. Wouldn’t it be great if we could tell PHP to reject the function call if $parameter is not of type Person? Decent, strong typed programming languages require all variables to be explicitly typed. In Java, we would define the previous function as follows:

      public void echoThisObject(Person parameter)
      {
            // We can safely call echoName now
            parameter.echoName();
      }

Can’t we do something similar in PHP? Oh yes we can!

      public function echoThisObject(Person $parameter)
      {
            if ($parameter instanceof Student)
            {
                  // We can safely call echoNameAndNumber now
                  $parameter->echoNameAndNumber();
            }
            else
            {
                  // We can safely call echoName now
                  $parameter->echoName ();
            }

      }

How about them apples, eh? Notice how we added the classname before the parameter? This is called type hinting. PHP will raise an error when you call the function with a parameter that is not instanceof Person. Also note that Student is a subclass of Person and as such is a Person.

Do mind that PHP’s type hinting is different from Java’s parameter declaration. In Java you can resolve the type system in compile time, which means that the compiler can check if you call the function properly. PHP doesn’t really have types and so there isn’t really a type system to resolve and so PHP doesn’t check diddly squat for you. If you’ve made a mistake, you can only find out by executing all possible paths through your code.

‘Can do’ relationships

There are two important practical and theoretical concepts that strongly involve polymorphism: abstract class and interface. An abstract class is a class that cannot be instantiated and can have zero, one or more methods left unimplemented. An interface is a named collection of methods that has no implementation whatsoever. Two quickie examples:

interface iLifeform
{
      public function die();
      public function eat();
}

abstract class aLifeform
{
      public abstract function die();
      public abstract function eat();

      public function someOtherMethod()
      {
            // do some stuff
      }
}

Abstract classes are extended in the same way normal classes are and can extend from classes like normal classes can. Interfaces are implemented by classes and can only extend and be extended by other interfaces. An interface cannot extend a class. Classes can only extend one class and implement as many interfaces as they want. Interfaces can extend as many interfaces as they like.

interface iMammal extends iLifeform
...

abstract class aMammal extends aLifeform
      implements iMammal, iSomeOtherInterface
...

I wrote a short article earlier about the differences between interfaces and abstract classes. Because I think using correct terms and definitions makes the world understandable and thus makes communication easier and thus reduces bickering and thus leaves more time = money, I think it’s very important to grasp where an interface differs from an abstract class. Polymorphism adds a dimension to this issue that I didn’t touch upon too much in the older article:

Abstract classes suck for polymorphism.

Oeh that was dangerous. Let me put it in a more respectable fashion. Polymorphism is not really about ‘is a’ relationships. Polymorhpism does not really care if you’re an instance of SuperProgrammer. Polymorphism is interested in what you ‘can do’. It is interested in contracts. And that’s exactly what interfaces are; interfaces ‘contractually’ bind an implementing class to implement the methods. That’s all. No is-a-bollocks, even though that is the mechanism PHP and many other languages use to determine can-do-awesomeness.

Does that mean that abstract classes are wrong for polymorphism? Aww, no of course not. But they are less powerful, because you can only extend one abstract class, so abstract classes tie you tightly into that inheritance tree. When I still did some Java, a long time ago, the Observable abstract class was a popular tool that I used for some homework assignments. But every class that extended from Observable could never extend from anything else anymore and so we had to implement iObservable instead and never use Observable. Waste of time.

Abstract classes are useful when you want to implement functionality without providing an instantiable unit, but when it comes to type hinting, I think interfaces are always better than abstract classes.

Werewolves are polymorph too! Image: nixxphotography / FreeDigitalPhotos.net

More to come

I will continue my series on OO through into software engineering with OO. I will talk about how you can use OO in practice and about the tools that are available to make your life easier. There is only one more left to go into all these theoretical things, I promise!

This article is part of the Object Oriented Programming series.

  1. Intro Object Oriented Programming
  2. Inheritance
  3. Polymorphism
  4. SOLID design
Pim Elshoff

About the author

Pim has been working the web since 2004! Read more about Pim

Comment(s)

Be the first to comment!

Trackbacks

No trackbacks yet

Leave a comment

All comments will be moderated

  Veld is verplicht
Captcha
  I'm terribly sorry that this is necessary and I appreciate the effort you are taking to post a comment!