abstract artFinal, abstract and other cousins

Counting classes in an application

How many classes are there in a PHP application? A simple count based on the class keyword gives a quick answer. Modern PHP application range from a dozen of units to a dozen of thousands.

Yet, each class keyword doesn’t produce a concrete class. Inheritance must be accounted for : inheritance merges several classes into one. The last child class is build on top of all the parent ones. That way, they act as one class only.

On the other hand, the parent classes may have a life of their own. Even as a partial class, it is possible to instantiate them. This is where the final and abstract keywords come into play.

Let’s review these features, and decide when to apply them.

Abstract, final and concrete classes

concrete classes

The most common type of class is the concrete class. Concrete classes are classes that are instantiated in the code. Then, such objects are processed by the application. Without any other coding option, classes are concrete classes.

abstract classes

The direct opposite of concrete classes are the abstract ones. Those must bear the abstract keyword. With it, PHP will prevent any instantiation. An abstract class must be inherited, and, when the child class doesn’t have the abstract keyword too, this might instantiated.

<?php
 abstract class Pot {}
 
 class Vase extends Pot {}
 
 $object = new Vase(); 
?>

Two side notes on abstract :

  • It also applies to methods. An abstract method must be in an abstract class. The contrary doesn’t apply : an abstract class doesn’t need to have an abstract method.
  • An abstract class may have abstract or concrete child, and vice versa : a concrete class may be the parent of an abstract class. This last class will need to be inherited yet again before being instantiated. Very unusual piece of code.

abstract classes are often presented as class templates. They design a number of constraints on the child classes, and enforce methods onto them. This is the conception approach, where templates are decided before coding. In this article, we review code, and figure out which could be abstract. That will cast a different light on the code.

final classes

final is rather on the opposite end of the spectrum to abstract. It prevents a class to be extended again. This means that afinal class is almost surely a concrete class : it cannot be inherited again, so its features must be accessible, via an object.

In fact, it is not possible to make a class that is both abstract and final : PHP complains at compilation time that Cannot use the final modifier on an abstract class. In practice, a single abstract class, or a class without option and never instantiated are possible : this is the case of static classes, gathering common tools as static methods. We’ll leave them out of this article.

Who’s final and who’s abstract?

Let’s review the possibilites, depending on the number of classes in a family.

 

One class

One may to use final and abstract with one class[/caption]

Let’s start with a single class. Then, only the final keyword is possible.

If we set aside considerations outside the scope of the code itself, then the class should be final. final keyword should actually be the default for such classes, until the need to extend them appears.

Two classes

With two classes, it is now possible to use abstract. Possible, and not compulsory : so the parent class may or may not be abstract. The parent cannot be final because, obviously, there wouldn’t be any child class.

By default, the parent class should bear the abstract option. After all, it is a partial class to the child one. Unless there is an instantiation, it is safe to do so.

Three classes (or more)

4 ways to make final and abstract classes with 3 classes
Lazy, classic, thorough, strange

With three classes, the class family grows, and a certain pattern emerges : the abstract classes are at the top, if any, and the final class at the bottom.

The lazy way is to leave out all the options, and keep them all unmarked.

How Abstract is a family ?

The abstract classes are not instantiated. So are non-instantiated parent classes supposed to be abstract ?

This is a tricky question : the intermediate classes are created to group certain methods or certains meaning within the class family. In the end of the development, if they are not instantiated, they shall as well be marked as abstract.

Indeed, it is easy to convert a child class to a parent class, since the classes are different aspects of the same object. In the example above, a Vase is also a Pot. That translation happens automatically with typehinting, for example.

On the other hand, the contrary is not possible : a Pot is not a Vase, and there are no easy way to convert a general class into a specific class. So, as soon as the class is a parent class, and non instantiated, it should be marked as abstract.

Reviewing a class family for final and abstract

Here are a few questions to ask when reviewing a class family :

The simplistic approach is to make all parent abstract and only the last children final. That way, any partial usage of the classes can be reviewed when the time comes to start using them independantly.

Until then, happy auditing!