Ever stumbled upon a PHP file that has the keyword `final` sitting in front of its class declaration and wonder what its doing? Today we want to shed some light on it and also talk about something that many developers don't do yet, but should (and why). 

In addition to the standard terms that are almost always used in inheritance - for example, `extends` or `parent::something()` - there are some more specific exceptions. These are comparatively rarely used, but should nevertheless be dealt with. Let's take a closer look at `final` and `abstract`.

Final specifies methods


Let's start with the easier one. Thanks to inheritance, we can overwrite the functionality of methods from their parent class in child classes and provide them with new functionality. As always, we will of course look directly at an example for this:

php
class Tree {
    public function grow()
    {
        echo "Grow grow grow";
    }
}

class Banana extends Tree {
    public function grow()
    {
        echo "Grow in Banana language";
    }
}

$regularTree = new Tree();
$bananaTree = new Banana();

$regularTree->grow(); // Grow grow grow
$bananaTree->grow(); // Grow in Banana language

In the example, we can see how the overwriting of methods works in a rather simple way. It depends on the class from which an object is created that the interpreter automatically calls the right method.

But what if we want to prevent a certain method from being overwritten? For example, if we want to open our class and make it available to other developers, we may not want to change the functionality.

This is exactly what the final keyword is for. If a method is declared with the keyword final, it can no longer be modified. If we change the above example as follows, we get an error.

php
class Tree {
    final public function grow()
    {
        echo "Grow grow grow";
    }
}

class Banana extends Tree {
    public function grow()
    {
        echo "Grow in Banana language";
    }
}

$regularTree = new Tree();
$bananaTree = new Banana();

$regularTree->grow(); // Grow grow grow
$bananaTree->grow(); // nothing, error

Our attempt to call grow on a class that extends another sub-class that has the method to be defined as `final` leads PHP to throw an exception, because we are attempting to override something that is marked as final. We don't want the Banana Tree to grow differently from our other Trees. 

Of course, we applied the `final` keyword here only to a method, not a class. We re-visit that later.

Abstract classes aren't too complex, either


`abstract` is basically the opposite of a `final` class (or a method). `abstract` classes cannot be called on their own, (i.e. instantiated), but instead we have to extend an `abstract` class from a more concrete class. Otherwise, there will again be Exceptions. PHP is pretty strict here, which is a very good thing for us.

A class that contains abstract methods must also be abstract. Abstract classes cannot be instantiated - so these only serve as parent classes. These classes therefore serve to define certain functionalities that should be present in various child classes.

If we define a method as `abstract`, this specifies that a class that inherits this method must also overwrite it. An `abstract` method may not have a method body, only the so-called signature (i.e. the name and the parameter list of the method) is defined.

php
abstract class Tree {

    abstract public function dropLeaves();

    public function grow()
    {
        echo "Grow grow grow";
    }
}

class Banana extends Tree {
    public function dropLeaves()
    {
        echo "*drop*";
    }
}

class Apple extends Tree {
    public function dropLeaves()
    {
        echo "*drops many*";
    }
}

$bananaTree = new Banana();
$appleTree = new Apple();

$bananaTree->grow(); // Grow grow grow
$bananaTree->dropLeaves(); // *drop*

$appleTree->grow(); // Grow grow grow
$appleTree->dropLeaves(); // *drops many* 

Now, there is quite something going on in here. Also, note how we did not create a new `Tree` class this time because its marked as abstract, so it would throw an error and prevent the following code from being executed.
  1. We have not specified the `grow` method in our concrete classes, yet we can call them. This is because the inheritance, we extended from a class that actually has the `grow()` method, so we can call it
  2. we defined `dropLeaves()` in both classes, so we can execute the code because the `abstract method public function dropLeaves();` has been implemented accordingly to the `Tree` abstract class

Both abstract and final are useful tools in the programming process flow as well as useful communication elements for collaborative development. If we create a class that is to be used by another developer, we can tell him which functionalities must remain exactly the same (final) or which functionalities he must extend or define himself (abstract). However, it can become quite complex when you have final methods. Now, its quite legitimate that a team of developers work for example with libraries. How should they be handled? 

The optimal approach with Interfaces


Instead of declaring many `final public functions`, instead we should only define `final class ...` instead. Why? Because it allows developers to code much more concrete (and abstract). In your `abstract` class, you should always define everything that is required to run a certain aspect of code. Lets think again of a `Tree`. A tree should grow, develop some fruits, drop the fruits to reproduce itself and when it becomes autumn, drop its leaves. But what if the Tree stands in a region that gets never cold? Right, the Tree should not drop leaves, because it should  continue doing photosynthesis. 

So, we would define our `Tree` class effectively like so:

php
abstract class Tree implements TreeInterface
{
    abstract protected function growFruits(): void;

    abstract protected function growLeaves(): void;

    abstract protected function dropLeaves(): void;

    abstract protected function hibernationMode(): void;

    abstract protected function dropFruits(): void;

    public function grow(): void
    {
        $this->growFruits();
        $this->growLeaves();
        $this->dropFruits();
        $this->hibernationMode();
    }
}

We again did some things. We declared `TreeInterface`, which defines what public methods have to exist in our `abstract class`. Now, since public methods add to an declarative interface already, most IDEs will be able to fetch the public method no matter what. But we implement it here for a completely different reason, that we will talk about later. 

Now, lets first see how concrete `Banana` and `Apple` would look like:

php
final class Banana extends Tree
{
    protected function growFruits(): void
    {
        echo 'I grew some bananas';
    }

    protected function growLeaves(): void
    {
        echo 'I grew some nice banana leaves';
    }

    protected function dropLeaves(): void
    {
        return;
    }

    protected function hibernationMode(): void
    {
        return;
    }

    protected function dropFruits(): void
    {
        echo 'I drop some bananas, they are too ripe now!';
    }
}

final class Apple extends Tree
{
    protected function growFruits(): void
    {
        echo 'I grew some apples';
    }

    protected function growLeaves(): void
    {
        echo 'I grew a pair of tiny apple leaves';
    }

    protected function dropLeaves(): void
    {
        echo 'I dropped some of my leaves';
    }

    protected function hibernationMode(): void
    {
        for($i = 0; $i < 3; ++$i) {
            $this->dropLeaves();
        }
    }

    protected function dropFruits(): void
    {
        echo 'Take some apples.';
    }
}

Oh boy! A lot of stuff happens now again. `Banana` is not meant to go into hibernation mode during "winter", because it can be warm enough for the tree to produce fruits the whole year. Because of this we made both `hibernationMode` and `dropLeaves` methods no-ops. They should not do anything. It looks much different for the `Apple`, tho. 

Now, why have we added Interface? The class only has one callable method. The reason is because we want not to inject concrete classes into methods or constructors, we want to inject interfaces, to keep our code strict but dynamic to work with different kinds of classes. 

Passing any tree would look like this now:

php
public method doSomething(TreeInterface $tree) {
    $tree->grow(); 
}

Instead of passing the Tree class as declaration. We could also get the Tree-name, if we would have a property that holds the Tree name, and not care about the class passed to `doSomething`, because its implementing an Interface that tells us exactly whats available there.

Now, if we want to test `doSomething` in a unit test, we don't want to create a concrete `Banana` or `Apple` class (we couldn't, because its final, but we can get ourselves a real class of the `Apple` instance, tho). We want instead to mock the Interface, because really thats everything want to do.

php
...
$mockTree = $this->createMock(TreeInterface::class);
$this->testClass->doSomething($mockTree);

This is much easier to read and maintain compared to initiating a new concrete class and passing it, however since much of this class is not really doing anything, its arguably why we shouldn't actually do it. In the past 20 years it was more state-of-the-art to do unit testing without any kind of extra integration checks, but its not bad, either. A developer team should decide what path they want to go and follow it very strictly.

Well, no matter how much knowledge you had about PHP classes before, you should be much smarter now and understand the concept a little better.

Long story short: make your Bananas always `final`, and the Tree definition `abstract`. If your framework allows it, of course. For example you cannot do it in Magento so well, but in Symfony its basically state-of-the-art.