Login

Abstract Classes in PHP: Introducing the Key Concepts

An abstract class is a class that cannot (or should not) be instantiated. They are surprisingly useful for certain purposes. In this article, you will learn the important concepts related to abstract classes in PHP 4, and see many hands-on examples that will allow you to make use of them in your own applications.

Introduction

Although PHP wasn’t originally conceived to include many object-oriented features found in full-fledged OOP languages, it has gone through different major rewrites. It now provides developers with a mature, rich language, which offers numerous improvements, particularly in an area known as Object Model. Admittedly, with the long-awaited release of PHP 5, the implementation of a powerful object model has dramatically changed the scenario most PHP programmers must tackle on a daily basis.

The introduction of strong object-based features, such as member visibility, interfaces, and exceptions –- to name a few -– has brought boosted capacities to all those developers wanting to take a deeper approach to using object-oriented programming. Generally speaking, one of the most interesting topics surrounding the object-based paradigm is the implementation of abstract classes inside of PHP applications, certainly a very useful concept when applied in the appropriate development context.

Throughout this article, the first of a three-part series, I’ll attempt to introduce the core concepts related to abstract classes in PHP 4, explaining some of their key features and exploring their implementation. Due to the fact I’m a loyal believer in the usefulness of code samples, I’ll hook up the corresponding theory to some illustrative hands-on examples, which hopefully will help you to better understand how you can use abstract classes in your own applications.

Of course, since PHP 5 is currently being widely adopted by programmers worldwide, I’ll also cover the use of abstract classes in PHP 5, which might be quite helpful for many developers starting to write code in the latest version of PHP.

By the end of this series, you should have a better idea of how abstract classes fit into the development of certain applications, and hopefully you’ll be equipped with the knowledge to decide how and when to put them to work for you.

Interested in learning more about abstract classes in PHP? Let’s get started.

What are abstract classes? Introducing the basics

Anyone who has spent considerable time using the object model provided by PHP 4 knows what a class is, but just in case you’ve forgotten this concept, let’s go over the basics quickly. In PHP a class is merely a set of statements that perform a specific task, and its definition contains both properties and methods, which act as the blueprint from which to create –- or instantiate -– independent objects.

That’s the theory for defining a regular class in PHP, so let’s go one step further and ask ourselves: what’s an abstract class? In the simplest sense, an abstract class is a class that cannot (and should not) be instantiated. This may sound a little illogical for beginning programmers, but there are situations where this concept makes a lot of sense.

To cite a case where an abstract class can be useful, allow me illustrate a typical situation: you’re developing an application where different classes are organized in a well-structured hierarchy. On top of this hierarchical relationship, you can define an abstract base class, which exposes a given number of generic properties and methods, in order to model the characteristics and behaviors of all its child classes.

From a purist point of view, this abstract class shouldn’t provide any explicit definition for its methods or properties. These methods and properties should be specifically defined within the subclasses, which automatically would inherit them from the base class. Indeed, this is a powerful concept that can be very useful when applied in the appropriate development context.

As I said before and strictly speaking, an abstract class should have no specific definitions for its methods. However, there are situations where it is convenient to define a base abstract class on top of the hierarchy, by encapsulating certain functionality when applicable. You would then derive as many classes as needed, which eventually will override or overload the methods inherited from the parent class.

As you can see, abstract classes are very handy for large Web applications, where a well-structured hierarchy of classes is often required. Certainly, this doesn’t mean that you have to define abstract classes here and there, whenever you can possibly use them. Most of the time, implementing abstract classes requires careful planning and study of the relationships between the classes that make up an application.

At this point, hopefully you’ve grasped the key concepts surrounding abstract classes in PHP. However, as you know, PHP 4 doesn’t have the ability to directly declare a class abstract, which implies having to write additional code to prevent such a class from being instantiated. Considering this issue, it’s time to go past the underlying theory, and illustrate different approaches to use in PHP 4 to avoid having a class be instantiated. Want to see how this is achieved? Keep on reading.

A simple method for coding a class that can’t be instantiated consists of including a simple “die()” statement inside its constructor. The example below demonstrates a simple way to implement this method:

The above example shows a very simple approach to preventing a class from being instantiated, by including a “die()” statement within the class constructor. After trying to instantiate an object from the sample “baseClass”, I get the following message:

This class is abstract. It cannot be instantiated!

And logically, the script is simply halted. Moreover, the above method is also effective if I ever want to statically call the constructor, by using the resolution scope operator (::), as listed below:

baseClass::baseClass();

This class is abstract. It cannot be instantiated!

In this case, the “die()” statement again displays a warning message and stops the execution of the script. For the first attempt at creating an abstract class, it’s not bad at all. However, a “die()” statement does not provide much control on program execution, so let’s move on and code another example of an abstract class. This time, we’ll use the “trigger_error()” PHP built-in function. Have a look:

Fatal error: This class is abstract. It cannot be instantiated! in path/to/file

As shown by the above example, I’ve coded the sample class so it triggers a fatal error whenever there’s an attempt to instantiate it. Here, I’ve used the magic constant __CLASS__ in order to prevent the class from being instantiated, which raises a fatal error when this happens.

Similar to the first example you saw earlier, if I ever want to statically call the class constructor, I get the same result:

baseClass::baseClass();

Fatal error: This class is abstract. It cannot be instantiated! in path/to/file

So far, I’ve defined a sample class that triggers a fatal error and, in consequence, halts the script when trying to spawn an object from it. This means that I’m very close to defining an abstract class in PHP 4. However, there are some issues to be addressed yet. The current definition of the sample class doesn’t prevent calling the constructor from a non child class. Taking this limitation into account, the next few lines will show you how to fix this problem. Scroll down the page and keep reading.

Since my original intention was to create a class that can’t be directly instantiated, even when called from non subclasses, I’ll build a very simple (and yet very useful) sample class, one that uses the PHP “is_subclass()” function, in order to avoid instantiation from non child classes. This new version of my sample class looks like this:

Fatal error: This class is abstract. It cannot be instantiated! in path/to/file

As you can see, now the sample class introduces additional checking code, in order to avoid allowing non subclasses to instantiate the base class. To achieve this, I’ve utilized the PHP “is_subclass()” function, which comes in handy for determining whether the base class is being called from a subclass.

At this point, I’ve created a base class that can’t be directly instantiated, and additionally refuses instantiation from any non child classes. However, I’m not completely satisfied with the code utilized by the class. It uses the __CLASS__ magic constant, which sometimes can lead to unexpected results, depending on the function with which this constant is included. Thus, let’s move forward and rewrite the code of the above sample class, so it’s able to use the PHP “get_class()” function, which, as you’ll see, will result in a more robust implementation of the abstract class.

{mospagebreak title=Optimizing the abstract class: using the PHP “get_class()” function}

In order to code a better version of the sample abstract class you saw previously, I’ll simply replace the __CLASS__ magic constant with the PHP “get_class()” function. Here’s the improved example of my “baseClass()”:

And, if I incidentally tried to instantiate the above class, I’d get the same fatal error:

$baseclass=&new baseClass();

Fatal error: This class is abstract. It cannot be instantiated! in path/to/file

As shown above, the sample class remains nearly the same. Actually, the only difference worth noting is the use of the “get_class()” function instead of the __CLASS__ magic constant, which makes the class slightly more efficient. The final improvement that I could introduce to the class code would be merging the two checking “if” blocks into only one statement, so the overall code is a little tighter. Considering the implementation of this minor change, the final version of the sample abstract class would be rewritten as follows:

Fatal error: This class is abstract. It cannot be instantiated! in path/to/file

As you can see, the above sample class now uses only one checking line to prevent its instantiation, which makes class code even more compact. Additionally, I’ve completely removed the ending “exit()” statement, since the previous “trigger_error()” function is raising a fatal error already, resulting in the script being immediately halted.

At this stage, hopefully I’ve demonstrated how to create a sample PHP 4 class that refuses any attempts to be instantiated, something that reminds us of the definition of an abstract class, which I explained right at the beginning of this article. You’ll probably want to study the core concepts and start coding your own abstract classes. Trust me, it’s an enjoyable and educational experience.

Bottom line

And that’s about all for the moment. In this first tutorial, you expanded your knowledge of object-based programming in PHP by actually using all the underlying theory of abstract classes to create a real, useful one. If you’re struggling to understand how abstract classes can be used in PHP applications, I hope this article offered some helpful pointers.

In the second part of this series, I’ll be using abstract classes to set up an instructive example, which will illustrate how to create a hierarchy of classes, handy for processing different types of data. See you in the next part!