final classes
In the past, when you didn't want other classes to extend a certain class, you could mark it as final.
Consider the code below :
<?php
namespace App\Utils;
class ParentClass
{
public function __construct(protected string $name) {
}
}
<?php
namespace App\Utils;
class ChildClass extends ParentClass
{
}
So we have a ParentClass and a ChildClass that extends the parent.
we could use the ChildClass as following:
<?php
use App\Utils\ChildClass;
$obj = new ChildClass('Antonio');
var_dump($obj);
And this would output ChildClass public properties and also inherited properties from ParentClass as follows:
Now if we do not want our class to be extended we just put the word final at the beginning of the class as follows:
<?php
namespace App\Utils;
final class ParentClass
{
public function __construct(
protected string $name,
) {
}
}
and calling the $obj = new ChildClass('Antonio'); again would result in: Class App\Utils\ChildClass cannot extend final class App\Utils\ParentClass.
So the definition of final in php is:
The final keyword is used to prevent a class from being inherited and to prevent inherited method from being overridden.
- So if we declare class method as a
finalthen that method cannot be override by the child class. - Same as method if we declare class as a
finalthen that class cannot be extended any more.
readonly class
readonly classes are added on PHP 8.2.
finaland readonlyare two completely different concepts in PHP and have different implications when applied to a class.
As we saw earlier, making a class final means that it cannot be extended.
final class ParentClass{}
// Fatal error: Class ChildClass cannot extend final class ParentClass
class ChildClass extends ParentClass{}
In the other hand, making a class readonly means several things:
- All instance properties of a class are implicitly marked as readonly, and cannot be reassigned.
- Creation of dynamic properties is not allowed.
- Only a readonly class can extend another readonly class.
- readonly properties can be overridden
For example:
// PHP 8.2+
readonly class ParentClass
{
public function __construct(
public string $name
) {}
}
$obj = new ParentClass('Antonio');
echo 'Hello, My name is ' . $obj ->name; // "Hello, My name is Antonio"
If you try to re-assign a value to any object property after instantiation, it would throw the following error:
// PHP 8.2+
// Fatal error: Uncaught Error: Cannot modify readonly property ParentClass::$name
$obj ->name = 'Ndershkuesi';
This happens because all properties are implicitly readonly when you mark the class as readonly.
NOTE: readonly property cannot have default value.
final and readonly
You can also mark a class as both readonly and final as well, this means:
- All class properties are implicitly
readonly. - The class cannot be extended.
Example:
// PHP 8.2+
final readonly class ParentClass {
public function __construct(
public string $name
) {}
}
Usage:
$obj = new ParentClass('Antonio');
echo 'My name is ' . $obj->name; // "My name is Antonio"
And if you try to assign a value to any object property or if you try to extend the class then it would throw an error as follows:
// PHP 8.2+
// Fatal error: Uncaught Error: Cannot modify readonly property ParentClass::$name
$obj->name = 'Ndershkuesi';
// Fatal error: Class ChildClass cannot extend final class Shape
readonly class ChildClass extends ParentClass {}
Was it helpful?
Let me know in the comment section below if you ever use this package in any of your projects.
Don’t forget to like and comment.
Follow me for more web development tips, new packages and more.
Thanks for reading.

Top comments (1)
Thanks for you effort. You still have a case that a readonly class extends readonly ParentClass. How are the constructors?