I am trying to learn OOP in PHP, and I have some confusion about interfaces and abstract classes. They both contain no implementations, only definitions, and should be implemented through their sub-classes. What part of abstract classes clearly distinguishes them from interfaces? Also, due to their apparent similarities, based on what reasons should I decide to use one over the other?
An abstract class can contain method implementations if the method is not defined as abstract. If the method is defined as abstract, it does not contain an implementation, but it needs to be implemented by its inheritors. An abstract class cannot be instantiated, but only inherited from, for the inheritor to allow it to use its behaviors.
An interface only defines method signatures and any class inheriting from it must implement all methods contained in the interface.
They both contain no implementations..
Abstract class can implements all or only part of the methods. But the main philosophy - is extend existing abstract class by to add a new methods in child classes (that extend a basic functionality).
In a child class you can extend only one class (abstract class). Abstract class define functionality that you must implement or just extends by other methods in child classes.
Interfaces are use to define the class behaviors. You can implement more than one interface(and say my child-class must do this,this and this thigs!), but you can extend only one abstract class.
An abstract
class forms an is-a relationship between itself and the subclass, while an interface
creates a follows-a relationship. As such, abstract classes are much more concrete than interfaces and they may also contain concrete implementations (e.g. Template methods) while an interface defines a contractual set of methods an implementing class must follow. This is a much higher level of abstraction as the implementing class must not necessarily be of the abstract class. Use it to standardize your API.
Related questions: http://stackoverflow.com/search?q=abstract+vs+interface
It is possible to create abstract classes that contain concrete members, such as methods or properties. You still can't instantiate the abstract class directly, but any instantiated sub-classes can benefit from implemented members defined in the abstract class.
An interface, by comparison, never contains any implementation logic. It is down to each implementing class to provide the implementation of all members defined in the interface.
In terms of how I view the differences, a sub-class of an abstract is-a class of that type. e.g. Dog
is an Animal
. I see an interface as a does-a relationship. e.g. ICanDisplayImages
tells me that the implementing class can display images, but tells me nothing about what the class actually represents.
Beyond the OOP philosophy described in other answers, I think the major use of abstract class is kind of a skeleton.
It's usefull when you design an application, or work with a team, because you have a base code to work with and extends it's close to interface but with a more advanced workflow.
Usually interfaces are used to define contracts, so you get type checking. There is also a programming style called "programming against interfaces", which is a good idea. See the Dependency Inversion Principle:
A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend upon details. Details should depend upon abstractions."
So if you define functions and methods, instead of type hinting against classes, you just hint against interfaces.
Here is an example. Let's say, you define interfaces for input streams and and output streams as follows:
interface OutputStream{
write($string); // Writes a string to the output.
close(); // Closes the output stream.
}
interface InputStream{
read($length); // Reads at most $length characters.
eof(); // TRUE, if the input stream is empty.
}
You could now create copy
function or method, which copies the complete output of a stream to an input, without having any of them:
// 50 is just chosen randomly.
function copy(InputStream $input, OutputStream $output){
while(!$input->eof()){
$output->write($input->read(50));}}
Congratulations, your copy
implementation now works for every combination of an input and output stream, without even implementing one.
Abstract classes, on the other hand, can be used to implement common functionality without having to implement a fully functional class.
Again, an example. Let's say, you want to have output streams. You want a method write($s)
, which writes a string to the output, and you want a method writeLine($s)
, which writes the string and an additional newline to the output. Then this would be appropriate:
abstract class AbstractOutputStream{
public function writeLine($s){
$this->write($s."\n");}}
Concrete output streams now could inherit from the abstract output stream, implement just write
and get writeLine
for free!