Menu
Coddy logo textTech

The final Keyword

Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 24 of 91.

While inheritance and method overriding provide flexibility, sometimes you need to prevent certain classes or methods from being changed. The final keyword locks down your code, ensuring that specific implementations cannot be altered by child classes.

When you mark a method as final, no child class can override it:

<?php
class BankAccount {
    protected $balance;
    
    public function __construct($balance) {
        $this->balance = $balance;
    }
    
    final public function getAccountId() {
        return "ACC-" . spl_object_id($this);
    }
}

class SavingsAccount extends BankAccount {
    public function addInterest() {
        return $this->balance * 0.05;
    }
}

$account = new SavingsAccount(1000);
echo $account->getAccountId();

Output:

ACC-1

The getAccountId() method cannot be overridden in SavingsAccount or any other child class. This protects critical functionality that must remain consistent across all account types.

You can also mark an entire class as final to prevent any inheritance:

<?php
final class SecurityManager {
    public function authenticate($user) {
        return "Authenticating $user";
    }
}

$security = new SecurityManager();
echo $security->authenticate("admin");

Output:

Authenticating admin

No class can extend SecurityManager. This is useful for security-sensitive classes or when the class design is complete and shouldn't be modified.

Key Point: Use final on methods to prevent overriding while still allowing inheritance, or on classes to prevent inheritance entirely. It's a tool for protecting critical code that must work exactly as designed.

challenge icon

Challenge

Easy

Let's build a document management system that demonstrates how the final keyword protects critical functionality from being modified by child classes.

You'll create three files that work together to manage different document types while ensuring certain security features remain locked:

  • Document.php — Define a Document class that serves as the base for all documents. It should have a public $title property and a protected $author property. The constructor accepts both title and author. Include a final method called getSignature() that returns "Signed by: [author]" — this security feature must never be altered by child classes. Also add a regular getContent() method that returns "Document: [title]".
  • Report.php — Define a Report class that extends Document. Include the Document file at the top. This class adds a $department property. The constructor should accept title, author, and department — use parent::__construct() for the first two, then set the department. Override the getContent() method to return "Report: [title] ([department])". The Report class inherits the final getSignature() method without being able to change it.
  • main.php — Include the Report file. You'll receive three inputs: the document title, author name, and department. Create a Report object with these values. Print the result of getContent() on the first line, then print the result of getSignature() on the second line.

This challenge shows how final methods protect critical functionality — the signature generation remains consistent across all document types, while other methods like getContent() can be customized by each child class. The Report can change how content is displayed, but the signature format is locked in the parent class.

Cheat sheet

The final keyword prevents classes or methods from being modified by child classes.

Final Methods: Mark a method as final to prevent child classes from overriding it:

<?php
class BankAccount {
    protected $balance;
    
    final public function getAccountId() {
        return "ACC-" . spl_object_id($this);
    }
}

class SavingsAccount extends BankAccount {
    // Cannot override getAccountId()
}

Final Classes: Mark an entire class as final to prevent any inheritance:

<?php
final class SecurityManager {
    public function authenticate($user) {
        return "Authenticating $user";
    }
}

// No class can extend SecurityManager

Use final on methods to protect specific functionality while allowing inheritance, or on classes to prevent inheritance entirely. This is useful for security-sensitive code or when implementations must remain consistent.

Try it yourself

<?php
require_once 'Report.php';

// Read input
$title = trim(fgets(STDIN));
$author = trim(fgets(STDIN));
$department = trim(fgets(STDIN));

// TODO: Create a Report object with the input values

// TODO: Print the result of getContent()

// TODO: Print the result of getSignature()
?>
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming