Understanding Abstract Classes in PHP
Abstract classes are an often misunderstood feature of PHP object-oriented programming (OOP) and the source of confusion when considered versus an Interface. The obvious reason for using an Interface is that a child class can implement multiple interfaces but extend only a single abstract class. However, if multiple inheritance is not required then people often go with abstract classes just because they provide the option of later adding base functionality within the abstract class. This is not entirely unreasonable but the reasons for creating abstract classes should be more than that.
Why Use Abstract Classes?
An Abstract class provides concrete base functions as well as abstract functions that must be implemented by concrete child classes—binding them into a contract so to speak, if they wish to make use of the base functionality.
This is a subtle but important point and this is where abstract classes really shine. They can call abstract functions from within base concrete functions. Jumping straight to an example is the clearest way to explain this.
abstract class Animal { function greeting() { $sound = $this->sound(); // exists in child class by contract return strtoupper($sound); } abstract function sound(); // this is the contract } class Dog extends Animal { function sound() { // concrete implementation is mandatory return "Woof!"; } } $dog = new Dog(); echo $dog->greeting(); // WOOF!
This opens up a whole lot of interesting possibilities. For example, you can write a drive()
function that calls $this->start(); $this->accelerate();
in an abstract class. Then create a motorcycle class that defines its own start()
and accelerate()
functions that may be different from those in the car class. In turn, the motorcycle and car can both be driven by just calling drive()
without having to implement it locally.
Characteristics of Abstract Classes
Make a note of these characteristics to lock down your understanding of abstract classes:
- Single inheritance. Child classes can extend only one class at a time.
- Abstract classes cannot be instantiated — no
new Animal();
- Abstract classes can define class variables of type const only.
- Abstract class A can be extended by another abstract class B. Abstract class B can implement none or any of the abstract functions in A.
- In the previous case, a child class C which extends abstract class B must implement all abstract functions in B as well as the abstract functions in A which have not already been implemented in B.
- The signature of the concrete functions and abstract functions must be the same. However, if an abstract function is defined as
abstract function speak($greeting);
then it is okay to implement it asfunction speak($greeting, $shout = FALSE)
but notfunction speak($greeting, $shout)
. - The visibility of functions in the child classes must be the same or less restrictive than the parent class. Thus, a
protected
abstract function can be implemented as eitherprotected
orpublic
but notprivate
. - Declaring functions as
static abstract
throws a strict warning in PHP 5.2 or earlier, however, as of PHP 5.3 this is allowed.
Good post in the first place.
Just to add more abstract classes, unlike interfaces, are classes. Here are some more characteristics of both of them:
Abstract classes can have consts, members, method stubs and defined methods, whereas interfaces can only have consts and methods stubs.
Methods and members of an abstract class can be defined with any visibility, whereas all methods of an interface must be defined as public.
When inheriting an abstract class, the child class must define the abstract methods, whereas an interface can extend another interface and methods don’t have to be defined.
A child class can only extend a single abstract (or any other) class, whereas an interface can extend or a class can implement multiple other interfaces.
A child class can define abstract methods with the same or less restrictive visibility, whereas a class implementing an interface must define the methods with the exact same visibility.
Good post , but please elaborate Interface more
Nice article, well explained. Just one little nagging comment: although the example is solid, unfortunately you don’t drive but ride a motorcycle… which would still make it awkward to call drive() in the Motorcycle class that extends your abstract class 🙂
thank you for your tutorials. Actually it was very helpfull to easily understand the core concept of abstract class in php.
Awesome. I am still a little confused regarding the usefulness of abstract classes. Isn’t the same thing accomplished using regular classes?
I never understood the use of abstract classes until we wrote a CMS at work.
Having an Abstract class for blocks or plugins seemed to make perfect sense as anyone trying to extend it would have to used a standard for example and all the code was a cleaner and there was no unearthing of OO madness.
echo $plugin->html() or echo $block->html() just seemed so much nicer to use.
I may be talking complete rubbish as I am only just using them in Real World Applications.