Before I ventured into the world of OO programming with PHP 4 I had spent the previous 20+ years programming in other languages, primarily COBOL and UNIFACE, and in all that time the word "interface" had only one meaning. As time went by I read more literature on OOP in general and PHP in particular in the hope of expanding my knowledge, but I kept coming across references to "interfaces" which seemed to imply a different meaning. This confused me as up until that point each word in the programming manuals had only one meaning, and each meaning was covered by only one word. Since the rise of the internet, instead of these manuals being edited and controlled by a central body, it seems that absolutely anyone and his dog can add their unedited opinions into the mix with the result that the concept of "one word, one meaning" has been broken. I now find that the word "interface" can have different meanings such as the following:
Every operation declared by an object specifies the operation's name, the objects it takes as parameters, and its 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 the object. An object's interface characterises the complete set of requests that can be sent to the object.
Unlike in procedural programming where a function can only be declared once, in OO programming a function, which is now called a method, can be repeated in multiple classes, and their signatures and implementations need not be the same.
This now means that "interface" means the collection of APIs that exist within an object instead of a single API.
When I started learning about OOP I understood that it was based around just three concepts - Encapsulation, Inheritance and Polymorphism - so where did Interfaces come from and what part do they play? I tried for years to find the real reason why they were created, but to no avail. All I kept reading were the same useless phrases being regurgitated over and over again about how important they were. The more I learned about the origins of interfaces the more I became convinced that they were a poor solution to a problem encountered in earlier languages which were strongly typed, but as PHP's is dynamically typed it does not allow this problem to exist, so it means that the solution does not have to be implemented as it is totally redundant. The rest of this paper follows my investigation into the need for interfaces and my conclusions regarding their implementation in PHP.
It wasn't until I came across an article called Polymorphism and Inheritance are Independent of Each Other that the true story was revealed. It would appear that object interfaces were designed to provide polymorphism in statically typed languages without the need for inheritance, as indicated in the following code samples:
// C++ polymorphism through inheritance class Car { // declare signature as pure virtual function public virtual boolean start() = 0; } class VolkswagenBeetle : Car { public boolean start() { // implementation code } } class SportsCar : Car { public boolean start() { // implementation code } } // Invocation of polymorphism Car cars[] = { new VolkswagenBeetle(), new SportsCar() }; for( I = 0; I < 2; i++) Cars[i].start();
The cars array is of type Car and can only hold objects that derive from Car (VolkswagenBeetle and SportsCar) and polymorphism works as expected. However, suppose I had the following additional class in my C++ program:
// C++ lack of polymorphism with no inheritance class Jalopy { public boolean start() { // implementation code } } // Jalopy does not inherit from Car, the following is illegal Car cars[] = { new VolkswagenBeetle(), new Jalopy() }; for( I = 0; I < 2; i++) Cars[i].start();
At compile time this will generate an error because the Jalopy type is not derived from Car. Even though they both implement the start() method with an identical signature, the compiler will stop me because there is a static type error.
One thing that has puzzled me for a long time is the need for code such as the following:
class VolkswagenBeetle : Car {...} class SportsCar : Car {...} Car cars[] = { new VolkswagenBeetle(), new SportsCar() };
The clue is in the last line where it is creating an array called cars
which can only hold objects of type Car
. This is a peculiarity of those languages which allow objects to have types which are independent of the class name. The way that the language authors "solved" this problem was to introduce a new concept called an interface which is used as follows:
// C++ polymorphism through an interface interface Car { public boolean start(); } class VolkswagenBeetle implements Car { public boolean start() { // implementation code } } class SportsCar implements Car { public boolean start() { // implementation code } } class Jalopy implements Car { public boolean start() { // implementation code } }
This issue does not exist in PHP. Objects do not have separate types, therefore it is not possible to prevent the use of objects of the wrong type. If you use the gettype() function on any object you will always get the same result, which is "object". Polymorphism in PHP does not require that the target object be of a certain type, only that it contains the specified method. The only real reasons why polymorphism would fail in PHP are as follows:
I find the idea of creating a separate subclass for each type of vehicle to be an alien concept in a database application. This is not how it is done. I would have a single table called Vehicle which would have a column called vehicle_type_id which would be a foreign key to a Vehicle_Type table. Each different vehicle would have a different row in the Vehicle table, and all rows in that table would be serviced within the same class. I would not have a separate table for each different type of vehicle, so why would I need a separate class? Why would I need a separate class for different rows in the same table?
It was not until many years later that I discovered that this situation was due to a restriction in languages which are statically typed. Languages like C++, for example, that use classes as user-defined types require that an object has the right superclass/supertype in order for it to receive a message, not just that it has the right protocol. This limitation does not exist in PHP as classes do not have separate types - each class is in fact its own type. When I instantiate a class into an object I do not have to specify the type of that object as all I need is the class name. This means that the following is valid in PHP:
// Jalopy does not inherit from Car, the following is perfectly legal
$cars = array{ new VolkswagenBeetle(), new Jalopy() };
Note that in PHP you cannot specify that each element in the array has a value of a particular type. An array can contain elements of any type, with the only limitation being that an array key must be either an integer or a string.
The aforementioned article raised the following question in my mind - if object interfaces were designed to create polymorphism without inheritance, then what is wrong with inheritance? That article had this to say:
Strong type checking imposed at compile time means that all polymorphism has to come through inheritance. This leads to problems with deep inheritance hierarchies and multiple inheritance where there are all kinds of problems with unexpected side effects. Even moderately complex programs become very hard to understand and maintain in C++.
[....]
The negative effects of the tight link between inheritance and polymorphism lead both Java and C# to introduce the concept of interface to pry apart the ideas of inheritance and polymorphism but keep strong type checking at compile time.
[....]
When type checking is deferred to runtime you can end up with strange behaviors when you make method calls to objects that don't implement the method, i.e. sending start() to an object with no start() method.
[....]
The one caveat to pure polymorphism is that we may develop subtle bugs that can be difficult to track down and fix. Pure polymorphism is only worth seeking if the language that you are using can reliably throw an exception when a method is not implemented.
As you should be able to see below the "problem" for which object interfaces were the solution concerned the following:
problems in some languages | non-problems in PHP |
---|---|
Strong type checking at compile time |
|
Type checking at runtime when calling a method which does not exist. In earlier languages which used a Virtual Machine (VM) this situation would cause the VM to abort, in which case it, and the program that was being run, had to be restarted. | If the method does not exist with a matching signature then PHP will throw an exception. |
Deep inheritance hierarchies | Never inherit from one concrete class to create another concrete class, always inherit from an abstract class. |
Multiple inheritance | You cannot inherit from more than one superclass, but you can achieve the same result using Traits. |
As these "problems" do not exist in PHP it should be obvious that the "solution" provided by object interfaces is totally redundant. Their usage should therefore be treated as a violation of the YAGNI principle.
As you should be able to see in the sample code shown in The "need" for object interfaces there is a Car
class which is inherited by both the VolkswagenBeetle
class and the SportsCar
class. This turns the Car
class into a superclass and the VolkswagenBeetle
and SportsCar
classes into subclasses. In strongly typed languages these are also known as supertypes and subtypes, and polymorphism is only allowed between objects which share the same type. This is why the Jalopy
class is rejected as it does not inherit from the same superclass. The language authors got around this limitation by creating a interface called Car
which can then be implemented instead of being inherited.
This tells me that object interfaces were created as a technique to circumvent a problem which existed in the earliest OO languages, and some bright spark invented a principle which says that you MUST keep using this technique even though the problem no longer exists in modern languages. This has a distinct smell of faecal matter to me.
That article also contains the following statements:
The original compiled languages (C++, etc) performed static type checking because of performance issues.
C++ was dominant until the mid 1990s simply because it was an object oriented solution that was NOT interpreted. This meant that on the slow CPUs of the time it had decent performance. We used C++ because we could not get comparable performance with any of the interpreted object-oriented languages of the time, i.e. Smalltalk.
It was only during the time frame when Java and C# were introduced that CPU power was sufficient for interpreted languages to give sufficient performance at run time. The transition from having polymorphism and inheritance tightly coupled to being more loosely coupled depended on run time interpreters being able to execute practical applications with decent performance.
He concludes with the following statement:
Effective programmers are seeking polymorphism and not inheritance. The benefits of pure polymorphism outweigh any advantage that compile time type checking provides, especially when we have access to very sophisticated debuggers and support for runtime exception handling. In general, I believe that the benefits of pure polymorphism outweigh the value of static type checking.
Although inheritance is the source of 99% of polymorphism in my framework, it is possible to have the same method signatures in multiple classes without inheritance simply by hard-coding them without using the keyword "implements". This is demonstrated in my framework where I have different Data Access Objects for each supported DBMS, and they each contain the same method signatures without the use of the keywords "extends" or "implements".
If Object Oriented Programming, as explained in What OOP is, is programming which is oriented around objects, thus taking advantage of Encapsulation, Inheritance and Polymorphism to increase code reuse and decrease code maintenance.
, then anything which does not contribute to this purpose should be avoided. If pure polymorphism is more beneficial than type checking then type checking, and anything which relies on it or enforces it, should be avoided.
Even though the problem for which object interfaces were the solution did not exist in PHP, they were introduced into PHP 5 because some OO fanboys thought that they were a fundamental part of OO theory. "Other proper OO languages have interfaces", they said, "so PHP should have them as well". What a foolish argument! I do not use interfaces as they serve no useful purpose, and my code works perfectly well without them. My framework is riddled with polymorphism which is provided mostly through inheritance, but where I don't use inheritance I also don't use interfaces. They are completely redundant in PHP, and I see their use as a violation of the YAGNI principle.
The fact that object interfaces are totally useless in PHP means that any principles which are based on them are also totally useless, such as the Interface Segregation Principle. I also find the notion that you should program to the interface, not the implementation to be totally ridiculous. I could not understand how a competent programmer could come up with such a foolish idea.
When I read about the Composite Reuse Principle (CRP) which promoted the idea that inheritance was bad I thought it was a joke. I had been using inheritance for years without any problems, so I could not see what was wrong with it. As I explain in Inheritance is NOT evil any problems are caused by its overuse, especially the bad habit of inheriting from one concrete class to create another concrete class. You should never inherit from a class that contains an implementation that you do no want. The way to avoid such problems is to only ever inherit from an abstract class, but apparently few programmers have the ability to create such reusable abstractions.
My usage of inheritance began after I created my first table class to handle the CRUD operations which are common to every database table. To deal with a second table I copied the code and changed all references from the first table to the second. This resulted in a lot of duplicated code, so I decided to find a way to reuse it from a single source and remove the duplication. I did this by moving the duplicated methods to an abstract class, removing these methods from each concrete class and reusing them by inheriting from the abstract class.
I later discovered that the path that I had chosen had been described as programming-by-difference in the paper Designing Reusable Classes which was published by Ralph E. Johnson & Brian Foote in 1988. I discuss their paper in my own article The meaning of "abstraction". While I placed the similarities in an abstract class I isolated the differences within each concrete class by using a set of common table properties which are loaded in by the class constructor, coupled with the use of "hook" methods to contain custom logic.
Polymorphism is not just about sharing method signatures without implementations as you are not sharing any code at all, you are just duplicating the method signatures and then providing a completely different implementation. Inheritance allows you to share method signatures as well as the code behind those signatures. The use of an abstract class also allows the use of the Template Method Pattern in which a series of invariant methods in the superclass can be mixed with variable or "hook" methods which can be customised within each subclass. Thus inheritance helps fulfil the purpose of OOP while object interfaces do not.
When Object Interfaces were added in PHP 5 I read the manual to find out what purpose they served and what benefits they could bring, and this is what I read:
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are implemented.
Interfaces are defined in the same way as a class, but with the interface keyword replacing the class keyword and without any of the methods having their contents defined.
Among its purposes it listed the following:
- To allow developers to create objects of different classes that may be used interchangeably because they implement the same interface or interfaces. A common example is multiple database access services ...
The phrase may be used interchangeably
sounded suspiciously like dependency injection which draws its power from polymorphism, but as I had already achieved massive amounts of polymorphism by having each of my concrete table classes inherit from a single abstract class I was at a loss to see what benefits object interfaces brought to the table. It was also obvious to me that you could use either one of these, but not both together, and as I had already witnessed first hand the benefits of using an abstract class what I read about object interfaces told me that I would loose all of these benefits, so I decided to ignore them completely.
The example of multiple database access services was even more confusing as I had already created two candidate classes for my Data Access Object which allowed me to switch between the original mysql API and the "improved" mysqli API. Both of these classes implemented the same set of method signatures, so it was easy to switch from one class to the other - all without the use of either inheritance or object interfaces. This led me to ask a very simple question - If I can achieve what object interfaces were designed to deliver without actually using them, what is the advantage of using them?
I tried running my code both with and without using the keywords "interface" and "implements", but there was absolutely no difference. This led me to the inevitable conclusion that the use of object interfaces in PHP was totally pointless as they don't actually do anything except become a waste of keystrokes. This also added to my growing suspicion that much of what is written about OOP is nothing but hype and that most of its proponents are know-nothing dogmatists who are in great danger of becoming nothing more than Cargo Cult Programmers.
Object interfaces were created to solve a particular problem, but time and time again I see them being described as necessary without reference to this problem. One reason is to follow the principle program to the interface, not the implementation
which I consider to be both illogical and unintuitive. Having written effective software without ever following this principle I cannot see how it can ever be justified. What bad thing happens if I don't follow this principle? What good thing happens if I do follow this principle? Where is a code sample which provides proof?
I do not understand what program to the interface
actually means.You cannot call a method in an interface as an interface is not an object. You can only call a method on an object which has been instantiated from a concrete class, so in order to call that method you must either be given an object that has already been instantiated, or you must instantiate it from a class yourself. If the method does not exist in the object with the correct signature then an error will be generated. If the method does exist but does not contain an implementation then it won't do anything and will not return a result. In other words you cannot just call the method, you must call something that implements that method otherwise all you will be doing is pissing in the wind.
In OOP Good Practices: Coding to the interface I read the following:
Coding to interfaces is a technique to write classes based on an interface; interface that defines what the behavior of the object should be. It involves creating an interface first, defining its methods and then creating the actual class with the implementation.
I could not follow this sequence when I developed the RADICORE framework as I started with PHP 4 which did not support these interfaces. After they had been included in PHP 5 I read about them and realised immediately that they would destroy all the reusability that I had created, so I decided to ignore them completely. Instead of treating this idea with Let's run it up the flagpole and see who salutes it
my preferred approach was more along the lines of Let's drop it in the toilet bowl and see who flushes it
.
My preferred technique, which over a decade later I read about in Designing Reusable Classes which was written by Ralph E. Johnson & Brian Foote, is to ignore interfaces completely and jump instead to build classes with hard-coded methods. After creating a number of classes you examine them looking for similarities and differences with the aim of moving the similarities to reusable components and the differences to unique components. You look for protocols (operations or methods) which are the same and move them to an abstract class. You can then remove these methods from your classes and instead inherit them from this abstract class. Note that by inheriting only from an abstract class you immediately remove any problems with inheritance. You also gain the advantage of being able to employ the Template Method Pattern which allows you to mix the shared methods in the abstract superclass with unique methods, known as "hook" methods, within each concrete subclass.
In What Is an Interface In PHP? I read the following:
PHP interfaces provide reusable types detailing specific behaviors that your application can consume. In particular, they allow you to create classes that have known, expected behaviors that fit within your own application architecture. PHP interfaces also allow you to substitute different implementations, regardless of normal class inheritance, giving you more flexibility in how your structure your applications.
I do not recognise the usage of the word "type" as labels for classes, objects or interfaces. In PHP it is not possible to allocate a type to a class or an object (refer to the gettype() function for details) as only scalars have Data Types.
Later on it says the following:
A PHP interface defines a contract which a class must fulfill. If a PHP class is a blueprint for objects, an interface is a blueprint for classes. Any class implementing a given interface can be expected to have the same behavior in terms of what can be called, how it can be called, and what will be returned.
I can understand that a class is a blueprint for an object, but if I want a blueprint for a class then I would place much more value on an abstract class than an interface. I cannot achieve with an interface what I can achieve with an abstract class. Furthermore, inheritance is one of the three pillars of OOP whereas interfaces were nothing but a botch that was added on later in some of the early languages to get around a problem with their faulty support for polymorphism coupled with the improper use of inheritance by poorly trained programmers.
Interfaces are not necessary in PHP. I do not need to define a contract before I write code to fulfil that contract. The word "contract" is not part of the OO vocabulary. When I call a method on an object the language does not check that I have implemented that method from an interface, or inherited it, it simply checks that the method exists in that object with that signature. If it does not then it will generate an error. PHP does not care how the method came to exist in that object, just that it does exist.
The problem which interfaces were designed to solve does not exist in PHP as it is weekly typed and not strongly typed. It has always been possible to define several classes with the same method signatures without the use of the keywords "extends" or "implements" and have those methods called in a polymorphic manner. This is precisely what I did when I created the Data Access Objects to deal with the different DBMS engines which I support. Polymorphism is not restricted to objects with the same "type" as objects do not have types.
If object interfaces are totally unnecessary in PHP, then why do so many people keep insisting that they are a "must have"? If they use a feature which they don't need then why don't they realise that they are violating the YAGNI principle? How can my critics complain that I am not following "best practices" when YAGNI is one of those practices which I am following and they are not? Telling me to do something which they fail to do themselves is a bit hypocritical, is it not?
It that isn't bad enough, when you consider that object interfaces were designed expressly to provide polymorphism without inheritance, and polymorphism only exists when the same interface is implemented in multiple classes, then if you create an interface which is only ever implemented in a single class then this is a double violation of YAGNI. Think about it. Using something that was designed to provide polymorphism, then using it WITHOUT providing polymorphism cannot by any stretch of the imagination be described as a "best practice".
To put it bluntly, object interfaces in PHP are as useful as a chocolate teapot. They do not provide any functionality, therefore they do not provide any reusable code, they are a waste of keystrokes.
Since a major motivation for object-oriented programming is software reuse every programmer should strive to produce as much reusable code as possible using the features provided in his programming language. This may include reusable classes which can be inherited or reusable objects which can be called. Object interfaces fail to provide any reusable code because they do nothing but define method signatures without any implementations. Inheritance provides the means whereby you can define one or more method signatures, with their implementations, in one class (known as a superclass) and then share those same methods and implementations in other classes (known as subclasses) just by using the "extends" keyword. When a subclass is instantiated into an object all those methods in the superclass are automatically available in that object as if they had actually been defined in the subclass.
One question that came to mind when I saw the sample code which rejected the Jalopy
class went as follows:
If theJalopy
class is supposed to be treated the same as theVolkswagenBeetle
andSportsCar
classes then why doesn't it inherit from the sameCar
class?
The only possible answer I could think of would be because the Car
class contains a method that shouldn't be made available in the Jalopy
class. This is a reason why some programmers complain that inheritance is bad and why it is better to favor composition over inheritance. While I encountered other articles which echoed the same sentiment nobody could explain precisely why inheritance was bad. Nobody could show me code samples of the two approaches which proved that one was better than the other, and without such proof I was not prepared to abandon my use of inheritance which I had been using to great effect in my framework for many years, and without any problems whatsoever. It wasn't until I read Object Composition vs. Inheritance that I found the following explanation:
Most designers overuse inheritance, resulting in large inheritance hierarchies that can become hard to deal with. Object composition is a different method of reusing functionality. Objects are composed to achieve more complex functionality. The disadvantage of object composition is that the behavior of the system may be harder to understand just by looking at the source code. A system using object composition may be very dynamic in nature so it may require running the system to get a deeper understanding of how the different objects cooperate.
.....
However, inheritance is still necessary. You cannot always get all the necessary functionality by assembling existing components.
.....
The disadvantage of class inheritance is that the subclass becomes dependent on the parent class implementation. This makes it harder to reuse the subclass, especially if part of the inherited implementation is no longer desirable. ... One way around this problem is to only inherit from abstract classes.
I also found similar text in the Gang of Four book which then made it obvious to me that the only way for inheritance to cause problems is when you inherit from one concrete class to create a completely different concrete class. The key is in the statement The disadvantage of class inheritance is that the subclass becomes dependent on the parent class implementation
. As a properly crafted abstract class should never contain any concrete implementations - that is what the concrete subclasses are for - then all the complaints about inheritance simply evaporate.
The problem is that the ability to create a properly crafted abstract class
seems to be beyond the abilities of large numbers of programmers. In the article Designing Reusable Classes, which was published in 1988 by Ralph E. Johnson & Brian Foote I read the following:
The most important attitude is the importance given to the creation of reusable abstractions. Kent Beck describes the difficulty in finding reusable abstractions and the importance placed on them by saying:Useful abstractions are usually created by programmers with an obsession for simplicity, who are willing to rewrite code several times to produce easy-to-understand and easy-to-specialize classes.
Decomposing problems and procedures is recognized as a difficult problem, and elaborate methodologies have been developed to help programmers in this process. Programmers who can go a step further and make their procedural solutions to a particular problem into a generic library are rare and valuable.
Note that I did not discover the Johnson & Foote article until many years after I had developed my framework, so it cannot be said that I followed their advice. I did what I did instinctively, and it turns out that my instincts were correct. I have written a response to this article in The meaning of "abstraction".
According to what is written in Designing Reusable Classes if several objects share the same protocols then those protocols should be defined in an abstract class (which may contain non-abstract methods) and then share them through inheritance. This means that what is defined in the abstract superclass does not have to be redefined in each concrete subclass. That is, of course, when you want to override the implementation. All those methods are magically copied into the resulting object when it is instantiated. This is not the case with interfaces where you first create the equivalent of an abstract class filled with abstract methods then in every class where you want to implement those signatures you first have to duplicate each signature before you can provide your own implementation. You are not reusing, you are duplicating.
The idea that abstract classes are better than interfaces was echoed in Design Principles from Design Patterns - A Conversation with Erich Gamma, Part III which contains the following:
This approach [using interfaces] gives you flexibility, but it also separates the really valuable part, the design, from the implementation, which allows clients to be decoupled from the implementation. One question is whether you should always use interfaces for that. An abstract class is good as well. In fact, an abstract class gives you more flexibility when it comes to evolution. You can add new behavior without breaking clients.
When you add a new method to an interface, you break all your clients. When you have an abstract class, you can add a new method and provide a default implementation in it. All the clients will continue to work. As always there is a trade-off, an interface gives you freedom with regard to the base class, an abstract class gives you the freedom to add new methods later. It isn't always possible to define an interface in an abstract class [see note below], but in the light of evolution you should consider whether an abstract class is sufficient.
Note: The statement It isn't always possible to define an interface in an abstract class
is out of date because in PHP an abstract class is allowed to contain both abstract and non-abstract methods, and an abstract method has exactly the same characteristics as an interface.
What he doesn't say in this interview but what he does say in his book is that abstract classes allows you to implement the Template Method Pattern which is described in the following way:
Template methods are a fundamental technique for code reuse. They are particularly important in class libraries because they are the means for factoring out common behaviour.
This means that the the generalised behaviour in the base class can be interrupted with specialised behaviour in each subclass. This implements the Hollywood Principle (Don't call us, we'll call you
) which is at the heart of framework design. Using these two - an abstract class and the Template Method Pattern - I have managed to build a framework for developing database applications with huge amounts of reusability and productivity.
I have used my framework to create a large ERP application which contains over 400 Model classes and 45 reusable Controllers. This means that I have 400 x 45 = 18,000 (yes, EIGHTEEN THOUSAND) opportunities for polymorphism. Trying to do that with interfaces instead of inheritance would require an enormous amount of effort for absolutely no benefit.
If I have so much polymorphism without any problems, does this mean that my efforts in creating abstractions which can be reused on such a large scale can be classed as "rare and valuable"?
I have written more on this topic in The difference between an interface and an abstract class.
My arguments against the use of object interfaces in PHP can be summarised as follows:
Here endeth the lesson. Don't applaud, just throw money.
These are reasons why I consider some ideas on how to do OOP "properly" to be complete rubbish:
21 Apr 2025 | Added Abstract classes are superior to object interfaces
Added Program to the interface Added Summary |