Tony Marston's Blog About software development, PHP and OOP

Polymorphism in PHP

Posted on 4th June 2025 by Tony Marston
What is polymorphism?
What do the Gang of Four say?
Specifying Object Interfaces
Dynamic Binding = Polymorphism
Specifying Object Implementations
Abstract Classes
Class versus Interface Inheritance
What do Johnson and Foote say?
Programming-by-difference
How can an object have a "type"?
Subtype Polymorphism is close, but not close enough
Pure Polymorphism is the closest
How to take advantage of polymorphism
Static Dependencies
Dynamic Dependencies
What are the benefits of polymorphism
Comments

What is polymorphism?

When I began teaching myself PHP in 2002 I relied on what was written in the online manual as well as some code samples I read in various books or found online. I found only two things that were missing:

  1. The language did not support the abstract keyword for classes, so I had to create my own generic class instead.
  2. The manual described encapsulation (how to create classes) and inheritance, but said nothing about polymorphism or how it could be used.

As I began to trawl the web for additional information on OOP in general and PHP's implementation of it in particular, I found various descriptions of polymorphism. The following is what I found on wikipedia in 2003:

In computer programming, type polymorphism refers to various ways of allowing a function or procedure to operate on multiple types of objects.

There are several distinct concepts, all of which are referred to as polymorphism:
PHP cannot categorise objects by type as only scalars have types.

I found these descriptions less than informative as they were written from the viewpoint of a compiled and statically typed language and not one which is interpreted and dynamically typed. In PHP the only objects are those which are instantiated from classes (it does not support value objects), and these cannot be categorised by type. You cannot assign a particular type to an object, and if you use the gettype() function on an object the answer will never be anything other than "object". It is only primitive data types that can be categorised by type. Code which references an object does not know about or even care about its type, just that it supports the method which is being called. Function overloading has nothing to do with class methods so I consider that referring to it as a type of polymorphism is very misleading.

The latest definition, as at March 2025, is also less than informative:

In programming language theory and type theory, polymorphism is the use of one symbol to represent multiple different types.

In object-oriented programming, polymorphism is the provision of one interface to entities of different data types. The concept is borrowed from a principle in biology where an organism or species can have many different forms or stages.

The most commonly recognized major forms of polymorphism are:

As soon as I read the phrases multiple types of objects and entities of different data types I began to hear warning bells in my head. In all my previous decades of programming in non-OO languages the term data type was limited to the values of individual items of data. As I investigated the capabilities of PHP I discovered that its type system did not give types to anything other than scalars or primitives. Collections of data items such as objects and arrays did not have types as each item in that collection could have a different type.

In Polymorphism In Programming I found this description:

In computer science, a polymorphic object is an object that is capable of taking on multiple forms. The kind of polymorphism the object undergoes depends on when the object takes its form and what part of the object is transforming.

This sounds backwards to me. It sounds like you instantiate a class into an object, and then decide what form that object should take. An object does not undergo polymorphism, nor does part of it undergo any sort of transformation because of polymorphism. The ability to provide polymorphism must be built into a class before it is instantiated into an object, not after.

What does the Gang of Four book say?

The Gang of Four are supposed to be recognised experts on all matters pertaining to OOP, so I bought a copy of their book, which was published in 1994, to see what they had to say on the subject of polymorphism. Extract from this book are discussed below under a series of sub-headings.

Specifying Object Interfaces

Every operation declared by an object specifies the operation's name, the objects it takes as parameters, and the operation's return value. This is known as the operation's signature. The set of all signatures defined by an object's operations is called the interface to that object. An object's interface characterises the complete set of requests that can be sent to the object. Any request that matches a signature in the object's interface may be sent to the object.

A type is a name used to denote a particular interface. An object may have many types, and widely different objects can share a type. Part of an object's interface may be characterised by one type, and other parts by other types. Two objects of the same type need only share parts of their interfaces. Interfaces can contain other interfaces as subsets. We say that a type is a subtype of another if its interface contains the interface of its supertype. Often we speak of a subtype inheriting the interface of its supertype.

Interfaces are fundamental in object-oriented systems. Objects are known only through their interfaces. There is no way to know anything about an object or to ask it to do anything without going through its interface. An object's interface says nothing about its implementation - different objects are free to to implement requests differently. That means two objects having completely different implementations can have identical interfaces.

This can be summarised as follows:

This is starting to become confusing. If a type identifies a particular interface and an object can have more than one type it infers that an object can have more than one set of interfaces. This contradicts the statement that The set of all signatures defined by an object's operations is called that object's interface. If the set of all signatures in an object is known as its interface, and a particular interface is known as a type, then all those signatures must belong to the same type. So how can an object have more than one type? This would imply that the collection of signatures for an object is comprised by combining the signatures from a collection of types (interfaces)

As I was developing my framework in PHP 4 I was guided by what was in the manual and what I read in books and online tutorials. None of them mentioned this thing called "interface", and none of them mentioned that objects could have "types". The keywords interface and implements were added in PHP 5, but after reading about them I could not see any advantage in using them, so I carried on inheriting from my abstract class.

The statement Interfaces are fundamental in object-oriented systems is wrong because object interfaces (which require the use of the keywords interface and implements) were only added to those strictly typed languages in order to provide polymorphism without inheritance. As far as I was aware the ONLY concepts which are fundamental to OOP are Encapsulation, Inheritance and Polymorphism. Everything else is nothing more than a language-specific extension.

Dynamic Binding = Polymorphism

When a request is sent to an object, the particular operation that's performed depends on both the request and the receiving object. Different objects that support identical requests may have different implementations of the operations that fulfill these requests. The run-time association of a request to an object and one of its operations is known as dynamic binding.

Dynamic binding means that issuing a request doesn't commit you to a particular implementation until run-time. Consequently, you can write programs that expect an object with a particular interface [method signature], knowing that any object that has the correct interface will accept the request. Moreover, dynamic binding lets you substitute objects that have identical interfaces for each other at run-time. This substitutability is known as polymorphism, and it's a key concept in object-oriented systems.It lets a client object make few assumptions about other objects beyond supporting a particular interface. Polymorphism simplifies the definition of clients, decouples objects from each other, and lets them vary their relationships to each other at run-time.

When I see the word "interface" I always wonder whether it is supposed to mean "method signature" or object interface (which requires the use of the keywords interface and implements) because they are different animals. I use "method signatures" in my code but never use object interfaces at all.

Now we have additional statements which can be added to the list:

I find the statement that polymorphism decouples objects from each other to be the wrong use of the term coupling. If ObjectA calls a method on ObjectB then ObjectA is dependent on ObjectB for part of its processing. This dependency means that the two objects are coupled, and this coupling can either be "tight" (without polymorphism) or "loose" (with polymorphism). Decoupling can only be achieved by removing the call (and hence the dependency) completely.

Specifying Object Implementations

Objects are created by instantiating a class. The object is said to be an instance of the class. The process of instantiating a class allocates storage for the object's internal data (made up of instance variables) and associates the operations with these data. Many similar instances of an object can be created by instantiating a class.

New classes can be defined in terms of existing classes using class inheritance. When a subclass inherits from a parent class [superclass], it includes the definitions of all the data and operations that the parent class defines. Objects that are instances of the subclass will contain all the data defined by the subclass and its parent classes, and they'll be able to perform all operations defined by this subclass and its parents.

All the documentation that I read talked about inheriting from a superclass to create a subclass. When others began writing about inheriting from supertypes to create subtypes I assumed that they were talking about the same thing as they were both achieved by inheritance. It was not until much later that I discovered that there were actually two types of inheritance.

Abstract Classes

An abstract class is one whose main purpose is to define a common interface for its subclasses. An abstract class will defer some or all of its implementations to operations defined in subclasses; hence an abstract class cannot be instantiated. The operations that an abstract class declares but doesn't implement are called abstract operations. Classes that aren't abstract are called concrete classes.

Subclasses can refine and redefine behaviours of their parent class. More specifically, a class may override an operation defined by its parent class. Overriding gives subclasses a chance to handle requests instead of their parent classes. Class inheritance lets you define classes simply by extending other classes, making it easy to define families of objects having related functionality.

Note here that an abstract class may contain a mixture of abstract and concrete (non-abstract) operations (methods) whereas an interface can only contain abstract methods. Because an abstract class can only be used to create concrete subclasses it is essential that any concrete methods do not contain implementations that would cause problems in any concrete subclass.

Class versus Interface Inheritance

It is important to understand the difference between and object's class and its type.

An object's class defines how the object is implemented. The class defines the object's internal state and the implementation of its operations. In contrast, and object's type only refers to its interface - the set of requests to which it can respond. An object can have many types, and objects of different classes can have the same type.

Of course, there's a close relationship between class and type. Because a class defines the operations an object can perform, it also defines the object's type. When we say that an object is an instance of a class, we imply that the object supports the the interface defined by the class.

Languages like C++ and Eiffel use classes to specify both an object's type and its implementation. Smalltalk programs do not decare the types of variables; consequently the compiler does not check that the types of objects assigned to a variable are subtypes of the variable's type. Sending a message requires checking that the class of the receiver implements the message, but it doesn't require checking that the receiver is an instance of a particular class.

It is also important to understand the difference between class inheritance and interface inheritance (subtyping). Class inheritance defines an object's implementation in terms of another objects's implementation. In short, it's a mechanism for code and representation sharing. In contrast, interface inheritance (or subtyping) describes when an object can be used in place of another.

This now identifies two types of inheritance:

This is saying that polymorphism, where one object can be used in place of (substituted for) another is only available by subtyping and not by subclassing. THIS IS RUBBISH! A subclass includes the definitions of all the data and operations that the parent class defines, so the subclass can be substituted for the superclass. If that superclass has a number of subclasses then those subclasses, because they share the same parent, are siblings, then any one of those siblings can be substituted for any other sibling.

This erroneous statement is corrected later when it says:

Class inheritance is basically just a mechanism for extending an application's functionality by reusing functionality in parent classes. It lets you define a new kind of object rapidly in terms of an old one. It lets you get new implementations almost for free, inheriting most of what you need from existing classes.

However, implementation reuse is only half the story. Inheritance's ability to define families of objects with identical interfaces [method signatures] (usually by inheriting from an abstract class) is also important, Why? Because polymorphism depends on it.

When inheritance is used carefully (some will say properly) all classes derived from an abstract class will share its interface. This implies that a subclass merely adds or overrides operations and does not hide operations of the parent class. All subclasses can then respond to the requests in the interface of this abstract class, making them all subtypes of the abstract class.

There are two benefits to manipulating objects solely in terms of the interface defined by abstract classes:
  1. Clients remain unaware of the specific types of objects they use, as long as the objects adhere to the interface that clients expect.
  2. Clients remain unaware of the classes that implement these objects. Clients only know about the abstract class(es) defining the interface.

Notice that it says that the proper way to use class inheritance is to only ever inherit from an abstract class. If you inherit from one concrete class to create a different concrete class then you may inherit an implementation that you do not want. It is the improper use of inheritance which led to the idea favour composition over inheritance. I ignore this practice for the simple reason that when I decided to share code through inheritance I got it right first time by creating an abstract class (but because PHP 4 did not support the keyword abstract I had to call it a generic class).

Item #2 in the above list does not apply to PHP as I never have to identify how an object obtained the method which I am just about to call, it only cares that the method actually exists.

There is another benefit from inheriting from an abstract class - it enables the use of the Template Method Pattern (which is described later in the GoF book), with its mixture of fixed/invariant methods and customisable/variant or "hook" methods.

What do Johnson and Foote say?

Many years after developing my framework I came across a paper called Designing Reusable Classes which was published in 1988 by Ralph E. Johnson & Brian Foote. Note that Ralph Johnson was also part of the Gang of Four. Here are extracts from that paper:

Polymorphism

Operations are performed on objects by "sending them a message" [calling a method]. Message sending causes polymorphism when the same message can be received by multiple objects.


Protocol

The specification of an object is given by its protocol, i.e. the set of messages that can be sent to it [the set of method signatures that it contains]. The type of the arguments of each message is also important, but "type" should be thought of as protocol and not as class. Objects with identical protocol are interchangeable. Thus, the interface between objects is defined by the protocols that they expect each other to understand. If several classes define the same protocol then objects in those classes are "plug compatible".

Standard protocols are given their power by polymorphism.


Inheritance

Class inheritance has a number of advantages. One is that it promotes code reuse, since code shared by several classes can be placed in their common superclass, and new classes can start off having code available by being given a superclass with that code. Class inheritance supports a style of programming called programming-by-difference, where the programmer defines a new class by picking a closely related class as its superclass and describing the differences between the old and new classes.

One of the important benefits of class inheritance is that it encourages the development of the standard protocols that were earlier described as making polymorphism so useful. All the subclasses of a particular class inherit its operations, so they all share its protocol.

Languages like C++ that use classes as types require that an object have the right superclass to receive a message, not just that it have the right protocol.

Now we are getting some different definitions:

Notice that it is only those languages which have strict typing which restrict polymorphism to those classes which share a superclass of the correct type or which implement the same object interface. PHP does not have strict typing, therefore this restriction does not apply. PHP4 did not support object interfaces, and even if it did I would never use the as I get more mileage out of abstract classes.

Programming-by-difference

It is the concept of programming-by-difference in their paper which really caught my attention. The idea is that you examine a collection of objects looking for patterns or similarities, then you try to separate the similar from the different so that you can put the similar into a reusable module (such as an abstract class) and the different into a separate module (such as a concrete class). This is discussed in more detail in The meaning of "abstraction".

If you identify that several objects share the same protocol then those objects are "plug compatible", which is another way of saying that one object can be substituted for another at run-time.

Abstract Classes

Standard protocols are often represented by abstract classes.

The roots of class hierarchies are usually abstract classes, while the leaf classes are never abstract.

A class that is not abstract is concrete. In general, it is better to inherit from an abstract class than from a concrete class. A concrete class must provide a definition for its data representation, and some subclasses will need a different representation. Since an abstract class does not have to provide a data representation, future subclasses can use any representation without fear of conflicting with the one that they inherited.

Creating new abstract classes is very important, but is not easy. It is always easier to reuse a nicely packaged abstraction than to invent it. However, the process of programming in Smalltalk makes it easier to discover the important abstractions. A Smalltalk programmer always tries to create new classes by making them be subclasses of existing ones, since this is less work than creating a class from scratch. This often results in a class hierarchy whose top-most class is concrete. The top of a large class hierarchy should almost always be an abstract class, so the experienced programmer will then try to reorganize the class hierarchy and find the abstract class hidden in the concrete class. The result will be a new abstract class that can be reused many times in the future.

Here the paper is saying that standard protocols are often placed in abstract classes which can then be inherited/shared multiple times in those concrete subclasses which implement the same protocol. When I am developing a database application I am writing software which interacts with objects in a database, not objects in the real world, and those objects in a database are called "tables". Irrespective of the fact that each table deals with different sets of data, every table is subject to the exact same set of operations which are Create, Read, Update and Delete (CRUD). This is why I have created an abstract table class to contain all the similarities and create a separate concrete subclass to contain the differences for each physical database table.

Abstract classes usually do not define any instance variables. However, they define methods in terms of a few undefined methods that must be implemented by the subclasses.

My own implementation does not recognise these restrictions.

How can an object have a "type"?

In the 20 years I spent programming in other languages before I switched to PHP with its object oriented capabilities, the only time that the word "type" was used was in reference to a value's data type. This was also reflected in Chapter 6. Types in the PHP manual. As I spent more time working with PHP and reading articles with the hope of learning more and improving my skills I started to see more and more usages of the word "type" in connection with an object instead of a value. Nowhere could a find an explanation of the differences between "data type" and "object type". Eventually I came across the following description:

In computer programming, an "object type" refers to a blueprint or template for creating objects, which are instances of that type. It defines the structure and behavior of all objects that belong to that type, including their attributes (properties) and methods (actions). Object types are fundamental to object-oriented programming and allow for the creation of reusable and organized code.

The phrase blueprint for creating objects sounds like the description of a class to me, so does that mean "class" and "type" are the same thing?

The statement Object types are fundamental to object-oriented programming is also wrong as it is NOT fundamental to OOP, it is an artificial restriction which was introduced into languages with strict typing. Languages which do not have this restriction are still capable of providing polymorphism. Polymorphism depends on different objects sharing the same method signatures, not the same type.

We now have two conflicting definitions - one that states an object type refers to a blueprint for creating objects (which is also the description of a class) and another which states an object's class is not the same as its type. Is this confusing or what?

PHP does not provide any mechanism either for defining an object's type or restricting the use of an object based on its type. If the use the gettype() function on an object the result will never be anything other than "object".

The only meaning of "object type" which makes any sense to me is the Evans Classification of the different kinds of domain objects:

Entities An object whose job is to hold state and associated behavior. The state (data) can be persisted to and retrieved from a database. Examples of this might be Account, Product or User. In my framework each database table has its own Model class.
Services An object which performs an operation. It encapsulates an activity but has no encapsulated state (that is, it is stateless). Examples of Services could include a parser, an authenticator, a validator or a transformer (such as transforming raw data into HTML, CSV or PDF). In my framework all Controllers, Views and DAOs are services.
Value objects An immutable object whose responsibility is mainly holding state but may have some behavior. Examples of Value Objects might be Color, Temperature, Price and Size. PHP does not support value objects, so I do not use them. I have written more on the topic in Value objects are worthless.

Subtype Polymorphism is close, but not close enough

Since the method of creating a subtype is exactly the same as creating a subclass as both use the same extends keyword I wondered why some people thought they were different. I wondered what was the difference between a supertype and a superclass, a subtype and a subclass. If both are classes which contain methods and properties which are inherited, and the sharing of methods (also known as protocols or interfaces) produces polymorphism, then what is the difference between inheriting from a supertype and inheriting from a superclass? What is the difference between a subtype and a subclass?

I found this example of subtyping on wikipedia which identified an object called bird as the supertype and objects called duck, cuckoo and ostrich as its subtypes, as shown in Figure 1:

Figure 1 - Subtype Polymorphism

subtype-polymorphism

I have seen other examples, such as in Polymorphism In Programming where the supertype is car with subtypes of Ford, Chevrolet, Kia, Nissan, Volkswagen, BMW, Audi, and Tesla. I also have another version using dogs and dog types in Databases do not support Subtypes.

As soon as I saw this diagram I had a serious attack of Whiskey Tango Foxtrot. I have been designing databases and the applications which use them since the 1980s, including hierarchical, network and relational databases. I am also very familiar with the process called Data Normalisation, and I can tell the difference between a table (file), a row (record) and a column (field). I have actually built several tables where the contents could be subdivided by type, but I have never done so. Why? Because the differences between one type and another do not require changes in the data structure, which means that the details for each entity (dog, bird or vehicle) can be stored in the same table. No sane database designer would ever store different rows in different tables, and no sane software developer would create different classes to deal with different rows in the same table. In such situations I would have on each table an additional column which identifies the "type" of each row/record, such as "dog_type", "bird_type" or "vehicle_type". The value of this column would either be taken from a hard-coded list or from a parent table. In this way I could add a new "type" by either amending the list or adding a new record to the parent table. It certainly would NOT involve creating a new class and all the other code required to interact with this new class.

As mentioned earlier subtype polymorphism uses inheritance, but it uses it in a peculiar and restrictive way as shown in the following example which I found in Treating objects as common groups:

This example is obviously from a compiled and strictly typed language as it will check that each of those classes has the correct type (which in this case is Vehicle), and if not the compilation process will fail. In a dynamically typed language such as PHP there are no restrictions regarding type when a class is instantiated into an object, as shown in the following:

Vehicle vehicle1 = new Car()  // compiled and statically typed
$vehicle1 = new vehicle;      // interpreted and dynamically typed

Because PHP is not compiled it cannot perform any checking at compile time, it can only be performed at run-time. Instead of being able to perform the check when the object is instantiated (which is impossible) it performs the check when a method is called. If the method does not exist it will throw an error.

I have no use for subtype polymorphism as I do not have subtypes in my database, nor do I have subtypes in my classes. I get everything that I need from pure polymorphism.

Pure Polymorphism is the closest

During my research I came across an article called Polymorphism and Inheritance are Independent of Each Other which opens with the following statements:

Flexible programs focus on polymorphism and not inheritance. Some languages focus on static type checking (C++, Java, C#) which links the concepts and reduces polymorphic opportunities. Languages that separate the concepts can allow you to focus on polymorphism and create more robust code. JavaScript, Python, Ruby, and VB.NET do not have typed variables and defer type checking to runtime. Is the value of static type checking worth giving up the power of pure polymorphism at runtime?

There are some important points there:

The article goes on to say:

Inheritance and polymorphism are independent but related entities - it is possible to have one without the other. If we use a language that requires variables to have a specific type (C++, C#, Java) then we might believe that these concepts are linked.

If you only use languages that do not require variables to be declared with a specific type, i.e. var in JavaScript, def in Python, def in Ruby, dim in VB.NET then you probably have no idea what I'm squawking about!

I believe that the benefits of pure polymorphism outweigh the value of static type checking. Now that we have fast processors, sophisticated debuggers, and runtime exception constructs the value of type checking at compile time is minimal.

Unfortunately all those languages which employ strict type checking insist on checking an object's type before it will allow polymorphism. As the only way of determining an object's type was by inheritance whereby the class name of the superclass (which is now called the supertype) then becomes the type of the subclass (which is now called the subtype) the language authors had to provide an alternative mechanism. In their infinite wisdom they chose to invent a construct called an object interface which could be "inherited" in a class by using the implements keyword. In this case an interface is exactly the same as an abstract class which is full of abstract methods with the only different being that a class can implement any number of interfaces but can only inherit from a single class.

Some struggle with polymorphism, so let's define it:

Polymorphism is the ability to send a message to an object without knowing what its type is.

That description fits PHP as objects do not have types therefore cannot be restricted by type:

This thing called "pure polymorphism" sounded like a good candidate, but what exactly does it mean? In this paper from the University of Texas I found the following description:

Pure polymorphism occurs when a single function can be applied to arguments of a variety of types. There is one function and a number of interpretations.

I do not like such phrases as they are not as precise as they should be. It is this lack of precision that leads to the possibility of different interpretations, and different interpretations can often lead to mis-interpretations. The word function should be changed to method signature. The phrase number of interpretations should be stated as different implementations of the same signature in different objects so as not to confuse it with operator overloading which means different implementations from different signatures in the same object. This can be rephrased as:

Pure polymorphism occurs when multiple objects, irrespective of their type, share the same method signature but have different implementations.

Notice where I have changed the wording slightly:

I do not consider operator overloading to be a special kind of polymorphism because its description is totally different:

Operator overloading is when the an object implements multiple signatures with the same name but where the arguments have different data types.

In PHP polymorphism can be provided by any collection of objects which share the same protocol (the same set of method signatures), and this can be achieved in the following ways:

  1. Hard-code the method signature, and its implementation, separately in each class that needs it.
  2. Inherit from a superclass that contains the methods you need. These methods may or may not be abstract, and the non-abstract methods may contain implementations.
  3. Implement an interface that contains the methods you need. These are all abstract methods so do not contain any implementations.

I use option #1 in all four of my Data Access Objects.

I use option #2 for all of my Model classes in the Business/Domain layer as every one represents a database table, and every database table, regardless of its contents, is subject to exactly the same set of protocols - namely Create, Read, Update and Delete (CRUD). According to Ralph E. Johnson & Brian Foote the best way to share the same protocol among multiple classes is to inherit from an abstract class.

I do not use option #3 anywhere in my code as object interfaces were created to solve a problem with strictly typed languages, and as PHP is dynamically typed and does not have this problem it does not need this solution. Adding code to do something which is not necessary would be a violation of the YAGNI principle.

How to take advantage of polymorphism

Having polymorphism available in your code is a waste of time unless to have the means to take advantage of it. What exactly does "plug compatible" and "substitutability" actually mean? This is actually the result of dynamic binding which has been defined as follows:

Dynamic binding lets you substitute objects that have identical interfaces for each other at run-time.

When your code is about to call a method on another object you are about to introduce a dependency into that code as it is now dependent on the contents of another object in order to complete its task. In order to instantiate a particular object from a list of candidate classes there are different choices depending on the size of the list, as shown below:

Static Dependencies

If the number of "plug compatible" or "substitutable" dependencies is small and fixed (i.e. static) then they can be handled using code similar to the following:

switch ($order_type) {
    case 'S':
        $class = 'order_header_s';
        break;
    case 'T':
        $class = 'order_header_t';
        break;
    case 'P':
        $class = 'order_header_p';
        break;
    default:
        trigger_error("INCORRECT VALUE FOR ORDER_TYPE", E_USER_ERROR);
} // switch
$dbobject = singleton::getInstance($class);
$fieldarray = $dbobject->insertRecord($fieldarray);

Notice here that I don't use a separate getInstance() method with each class, instead I use a separate singleton class.

Dynamic Dependencies

It wasn't until the publication of the Dependency Inversion Principle in 1996 by Robert C. Martin that act of switching dependencies at run-time was given a name - Dependency Injection (DI). This is where the list of candidate classes is potentially very large and variable (i.e. dynamic), in which case the code which chooses the dependent object is in a different place from that which uses that object. In the RADICORE implementation the component which chooses the dependency is called a component script while the component which uses that dependency is known as a controller script, as shown in the following code samples:

-- a COMPONENT script (mnu_user(add1).php)
<?php
$table_id = "mnu_user";                      // identifies the model
$screen   = 'mnu_user.detail.screen.inc';    // identifies the view
require 'std.add1.inc';                      // activates the controller
?>

Note that this example uses the 'add1' controller, although there are over 40 different controllers, one for each of my Transaction Patterns. This script "injects" the name of the target class file into the designated Controller using the variable $table_id.

-- a CONTROLLER script (std.add1.inc)
<?php
require "classes/$table_id.class.inc";
$object = new $table_id;
$fieldarray = $object->insertRecord($_POST);
if (empty($object->errors)) {
  $result = $object->commit();
} else {
  $result = $object->rollback();
} // if
?>

When my critics told me that I should be using dependency injection for every dependency I had to look it up on wikipedia to find out what they were talking about. I didn't like what I read, and I was in no mood to change my code to implement one of the recommended types of dependency injection, so I wrote a new article called Dependency Injection is EVIL instead. It was while writing this article that I realised that I was already using DI in my code, but with a method which was not on their list.

Here is a list of of the recommended types of dependency injection:

Here is the new one which I invented:

Please note the following:

What are the benefits of polymorphism

Having defined what polymorphism is, how it can be created and how it can be used, the final question is why should it be used? What are the benefits? When I began to use the OO capabilities of PHP the first question I asked was What is Object-Oriented Programming? This lead me following definition:

Object-Oriented Programming: Writing programs which are oriented around objects. Such programs can take advantage of Encapsulation, Inheritance and Polymorphism to increase code reuse and decrease code maintenance.

The ability to increase code reuse seemed a worthy goal as my previous experience had already told me that the more reusable code you have then the less code you have to write to get the job done, and the less code you have to write then the less time it will take to get the job done and the more productive you will be. In order to achieve this you must be good at spotting patterns, things which are repeated several times which appear as collections of similarities with some differences. These patterns can appear in either behaviour or structure. When you find a pattern the trick is to separate the similarities from the differences so that you can place the similarities in some sort of reusable module and isolate the differences in separate unique modules. This is described by Johnson & Foote as programming-by-difference.

In order to spot patterns in your code, especially patterns that can be converted into reusable objects, you need to avoid those principles and practices which bury the similarities under a mountain of differences so that they become impossible to spot. Here are two practices which I avoid like the plague:

Now image you have a number of objects called Models which contain non-reusable methods which are called from a series of non-reusable objects called Controllers. Due to these non-reusable methods each of the Models will require its own Controller which means that each Controller is tightly coupled to a single Model. In Figure 2 below the Models are labelled M1-M5 and the Controllers are labelled C1-C5:

Figure 2 - Tightly coupled non-reusable objects

polymorphism-01

Now imagine that each of those Model classes supports the same set of reusable methods. Using the mechanism described in dynamic dependencies these objects become loosely coupled which means that a single Controller could be used to access any Model, as shown in Figure 3 below:

Figure 3 - Loosely coupled reusable objects

polymorphism-01

However, I do not have a single multi-purpose Controller in my framework. Instead of a single Controller which handles all the operations for a Model I have a separate Controller for each distinct operation. This produces a family of forms as shown in Figure 4 below:

Figure 4 - A typical Family of Forms

LIST1 ADD1 DELETE1 ENQUIRE1 SEARCH1 UPDATE1 dialog-types-01 (1K)

Note that each of the boxes in the above diagram is a clickable link.

These six Controllers were just the start as they could only deal with a single database table without any relationships. As time went on I found situations which required different Controllers to deal with different relations, such as one-to-many and many-to-many, or different outputs such as CSV or PDF (instead of the standard HTML), tree views and timetables. These are all described in Transaction Patterns for Web Applications.

By only following only those practices which enable the production of as much reusable code as possible I have been able to produce a framework which provides exceptional levels of reusability and high levels of productivity. As an example I point you to the GM-X application suite which was developed using the RADICORE framework. This currently is comprised of the following:

This is all provided by the following:

What this means in real terms is that every database table class follows the same pattern by inheriting all its standard code from an abstract table class, and every user transaction follows the same pattern by being a mixture of boilerplate code (which carries out the processing which is common to all transactions of that type) and custom code (which is unique to individual transactions). Using the framework a developer can generate and then run basic working transactions at the touch of a few buttons without writing any code - no PHP, no HTML, no SQL. All that is left for the developer to do is to insert the relevant custom code into the relevant "hook" method.

How many frameworks offer this number of reusable components?

Here endeth the lesson. Don't applaud, just throw money.


counter