When to use Final in PHP?

I know what the definition is of a Final class, but I want to know how and when final is really needed.

<?php
final class Foo extends Bar
{
   public function()
   {
     echo 'John Doe';
   }
}

If I understand it correctly, 'final' enables it to extend 'Foo'.

Can anyone explain when and why 'final' should be used? In other words, is there any reason why a class should not be extended?

If for example class 'Bar' and class 'Foo' are missing some functionality, it would be nice to create a class which extends 'Bar'.


Solution 1:

There is a nice article about "When to declare classes final". A few quotes from it:

TL;DR: Make your classes always final, if they implement an interface, and no other public methods are defined

Why do I have to use final?

  1. Preventing massive inheritance chain of doom
  2. Encouraging composition
  3. Force the developer to think about user public API
  4. Force the developer to shrink an object's public API
  5. A final class can always be made extensible
  6. extends breaks encapsulation
  7. You don't need that flexibility
  8. You are free to change the code

When to avoid final:

Final classes only work effectively under following assumptions:

  1. There is an abstraction (interface) that the final class implements
  2. All of the public API of the final class is part of that interface

If one of these two pre-conditions is missing, then you will likely reach a point in time when you will make the class extensible, as your code is not truly relying on abstractions.

P.S. Thanks to @ocramius for great reading!

Solution 2:

For general usage, I would recommend against making a class final. There might be some use cases where it makes sense: if you design a complex API / framework and want to make sure that users of your framework can override only the parts of the functionality that you want them to control it might make sense for you to restrict this possibility and make certain base classes final.

e.g. if you have an Integer class, it might make sense to make that final in order to keep users of your framework form overriding, say, the add(...) method in your class.

Solution 3:

The reason are:

  1. Declaring a class as final prevents it from being subclassed—period; it’s the end of the line.

  2. Declaring every method in a class as final allows the creation of subclasses, which have access to the parent class’s methods, but cannot override them. The subclasses can define additional methods of their own.

  3. The final keyword controls only the ability to override and should not be confused with the private visibility modifier. A private method cannot be accessed by any other class; a final one can.

—— quoted from page 68 of the book PHP Object-Oriented Solutions by David Powers.

For example:

final childClassname extends ParentsClassname {
    // class definition omitted
}

This covers the whole class, including all its methods and properties. Any attempt to create a child class from childClassname would now result in a fatal error. But,if you need to allow the class to be subclassed but prevent a particular method from being overridden, the final keyword goes in front of the method definition.

class childClassname extends parentClassname { 
    protected $numPages;

    public function __construct($autor, $pages) {
        $this->_autor = $autor;
        $this->numPages = $pages;
    }

    final public function PageCount() { 
        return $this->numPages; 
    }
}

In this example, none of them will be able to overridden the PageCount() method.

Solution 4:

A final class is one which cannot be extended http://php.net/manual/en/language.oop5.final.php

You would use it where the class contained methods which you specifically do not want overridden. This may be because doing do would break your application in some way.

Solution 5:

My 2 cents:

When To Use final:

  • NEVER!!

Why?

  • it breaks the ability to use test doubles when unit testing
  • could lead to increased code duplication because of gaps in functionality in downstream code
  • the reasons to use it are all training issues being addressed with a radical shortcut

Bad Reasons to Use It:

  • Preventing massive inheritance chain of doom (training issue)
  • Encouraging composition (training issue)
  • Force the developer to think about user public API (training issue)
  • Force the developer to shrink an object's public API (training issue? code reviews?)
  • A final class can always be made extensible (relevance?)
  • extends breaks encapsulation (what? poor encapsulation breaks encapsulation; not inheritance. inheritance is not inherently evil.)
  • You don't need that flexibility (typical thinking behind short-sighted development. be prepared to hit a feature wall + training issue)
  • You are free to change the code (relevance?)