The "final" keyword

#CleanCode

The official doc.

The final keyword prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final then it cannot be extended.

#CleanCode

As well, a method can be declared as final. Therefore, the class can still be extended but the method marked as final is not overridable.

Concrete example

#CleanCode

final class Person
{

    public function sayMyName($name){
        return "My name is $name";
    }

}

class Man extends Person {

    public function sayMyName($name){
        return parent::sayMyName($name)." and I am a man";
    }
    
}

Examples in OS projects
Doctrine

#CleanCode

namespace Doctrine\ORM;

/** A Query object represents a DQL query. */
final class Query extends AbstractQuery
{
    public function getSQL() {
        ...
    }

    public function setQueryCacheDriver($queryCache) {
        ...
    }

    public function useQueryCache($bool) {
        ...
    }

    public function getQueryCacheDriver() {
        ...
    }
}

Examples in OS projects
ElCodi

#CleanCode

namespace Elcodi\Component\Cart;

final class ElcodiCartEvents
{

    const CART_PRELOAD = 'cart.preload';

    const CART_ONLOAD = 'cart.onload';

    const CART_ONEMPTY = 'cart.onempty';

    const CART_INCONSISTENT = 'cart.inconsistent';

    const CARTLINE_ONADD = 'cart_line.onadd';

    const CARTLINE_ONEDIT = 'cart_line.onedit';

    const CARTLINE_ONREMOVE = 'cart_line.onremove';

    const ORDER_PRECREATED = 'order.precreated';

    const ORDER_ONCREATED = 'order.oncreated';

}

But...

#CleanCode

But there are not so many examples...

The feeling we had, looking for OS projects using the keyword is simple: people use it all the time, or do NOT use it at all.

Therefore... we decided to look for PHP trusted developer's opinion.

Ocramius (AKA Marco Pivetta)

Working in the core team of Doctrine

#CleanCode

His opinion: final should be used whenever possible

Some of the facts justifying his opinion are:

  1. Preventing massive inheritance chain of doom.

  2. Force the developer to think about user public API.

  3. “extends” breaks encapsulation.

 

But he also thinks the final keyword should not be used when:

  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.

 

Joshua Boch

Software engineer and a technology author,
formerly employed at Sun Microsystems and Google

#CleanCode

His opinion:  classes not intended to be subclassed should be marked final. The idea is that an extensible by inheritance classes should be carefully constructed and documented

Random but funny guy...

#CleanCode

His opinion:  don’t do final unless you absolutely have to and you’re exhausted of everyone’s else opinions.

We like

#CleanCode

  1. Forces us to use composition over inheritance

  2. Forbids us from mocking objects (you should be mocking interfaces, not implementations)

  3. Forces the user to think of his implementation and its logic instead of just extending a given class

  4. In open source projects, being sure no one will extend your own logic.

We don't like

#CleanCode

  1. Might scare a developer when beginning on a new project
     

  2. Symfony DI related: We can’t extend the class, therefore, we can’t declare a service as lazy in Symfony.

So, what's the point?

#CleanCode

Globally, the community like and advice to use the "final" world.

 

Declaring a class "final" ensure no one will extend it. Supposing that the implementation you've done is valid and has a single responsibility, why would someone extend it?

 

Then, the war might just be a question of habit...