12
Why are interfaces widely ignored in the PHP world and what use do they have when working with symfony?
28 Comments · Posted by Christian in Good to know
Every once in a while I stumble upon interfaces or somebody mentions them to me. Whenever this happens I realise that the use of Interfaces as an OOP key feature in PHP is next to none at all. But why is that?
Try to google for “php interfaces” and you will get mostly three different kind of results.
- Links to the OO/interface section of the PHP manual
- Links to website explaining how to use interfaces for dummies
- Links to discussions about the difference between interfaces and abstract classes
What you will rarely see is a link to an interface used in some project. Also if you grep the core of symfony you will find 9 Interfaces for Doctrine, 14 for phing, 11 for Propel and 44 for swiftmailer. symfony itself defines 4 interfaces only.
And symfony is no exception. While interfaces a very common in languages like Java they are almost not present throughout many PHP projects. But why?
What are interfaces?
The best description I could find so far is: An interface is a contract.
- An interface defines public methods that a class needs to implement
- An interface does not contain any code
- A class can implement multiple interfaces
- Interfaces can be used for type hinting
Basically if you see a class implementing an interface you know how to use it no matter how the implementation within the class is achieved.
What are abstract classes?
- An abstract class can implement methods (code)
- An abstract class can define abstract methods (no code)
- An abstract class can not be instantiated
- Classes can only inherit from one abstract class
And the difference is now what?
Abstract classes and interfaces are in some ways similar but they do each have their unique use cases.
The simplest rule is:
- If you write an abstract class containing only abstract methods you use an abstract class as an interface.
On many sites discussion the differences you will find that the fact that many interfaces can be implemented but only one abstract class can be inherited from is the main distinction.
In my humble opinion that is not the case. I even think that classes implementing many interfaces are likely (not always) to be badly designed as many interfaces probably means many concerns within one class.
The main difference is that abstract classes already provide implementations of methods and interfaces do not.
This implies that there is a different concept behind both constructs.
Methods inherited from abstract classes imply that the shared implementation is common to all descending classes.
Methods defined in an interface imply that their implementation needs to be dedicated to the implementing class.
A simple example for an interface is sfLoggerInterface.
interface sfLoggerInterface
{
/**
* Logs a message.
*
* @param string $message Message
* @param string $priority Message priority
*/
public function log($message, $priority = null);
}
It defines only a single method log() and if you think about it you will realise that though the job if this method is the same no matter what the implementation is the details will be very different whether you log to a file, a database, syslog or somewhere else.
A simple example for an abstract class does not exist as abstract classes should always contain code. But a simple enough example is sfCache.
In sfCache you will find implementations of methods that are thought to be common throughout all cache classes. The effect of this is of course to avoid duplicate code.
It also defines a few abstract methods where the implementation will be uncommon.
Now you could argue to strip sfCache from all abstract methods and move them to an interface. But other than to server your academic motivation what benefit would it have? It would only create a new file that does not make sense on its own and so would increase the overall complexity.
See what the Java tutorials say about this.
Unlike interfaces, abstract classes can contain fields that are not static and final, and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.
Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example.
By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods).
(taken from java.sun.com)
As a rule of thumb you could define the following:
- Use abstract classes to share function
- Use interfaces to share usage
I guess one of the reasons why interfaces are not used very often by PHP developers is that in PHP you often start to code right away and you would start thinking sharing code later on when you have something to share. This way around you rarely consider contracts as the usage is already developed and negotiated. This can be considered bad practice of course and probably should be but it is my only explanation for the lack of interfaces out there.
How to handle interfaces if working with a framework?
Of course the use of interfaces and abstract classes when working within a framework are no different to the above. There are however things you should consider about when to use them.
Many developers especially in the Java world are used to design interfaces before the implementation. They build the contracts first and determine how the interaction of classes works before starting to code.
However in frameworks such as symfony a good deal of the coding is done via scaffolding and code generation. There is no point to define interfaces for generated code!
Take models for example no matter if generated by Propel or Doctrine, there is no need to write an interface defining all the getters and setters and such because the classes are not implemented against this interface. They are generated against their schema. The schema defines the interface.
Now of course you will add custom methods to the generated classes but will you really implement an interface on more than one class? If not what’s the point? And if isn’t the implementation of it the same for all classes?
In most cases I assume that you want to define a common behaviour for you models. You want them to share some methods and attributes. Now in Doctrine you should probably create a behaviour for this and specify it in the schema of your models. The code in the case would not be implemented (duplicated) nor would it be inherited instead it would be delegated. I’m not sure but there is probably a similar feature in Propel.
And always ask yourself if you really do share the usage across all classes that should implement your interface. Will you ever pass objects to a method that have a common interface but no common implementation (parent class) ?
There will be situations where all this is appropriate no doubt about it. But for the best part of your work you will deal with models, controllers and templates and the interaction is defined already by the framework..
Abstract Classes · Design · Interfaces · PHP · symfony


Pingback: Tweets that mention • Why are interfaces widely ignored in the PHP world and what use do they have when working with symfony? | test.ical.ly -- Topsy.com
Pingback: Max’ Lesestoff zum Wochenende | PHP hates me - Der PHP Blog
Pingback: PHP: When to use an Interface
Pingback: Interfaces Make Testing Easier | BrandonSavage.net
Pingback: Revue de presse Industrialisation PHP de la semaine 23 (2010) | Industrialisation PHP
Pingback: • This was 2010 – test.ical.ly continues in 2011! | test.ical.ly
Pingback: Interface vs. Abstract class en PHP – castellano « Alessio Mavica