Ключевое слово "final"
PHP 5 представляет ключевое слово final, разместив которое перед объявлениями методов класса, можно предотвратить их переопределение в дочерних классах. Если же сам класс определяется с этим ключевым словом, то он не сможет быть унаследован.
Пример #1 Пример окончательных (final) методов
<?php
class BaseClass <
public function test () <
echo «Вызван метод BaseClass::test()\n» ;
>
final public function moreTesting () <
echo «Вызван метод BaseClass::moreTesting()\n» ;
>
>
class ChildClass extends BaseClass <
public function moreTesting () <
echo «Вызван метод ChildClass::moreTesting()\n» ;
>
>
// Выполнение заканчивается фатальной ошибкой: Cannot override final method BaseClass::moreTesting()
// (Метод BaseClass::moretesting() не может быть переопределён)
?>
Пример #2 Пример окончательного (final) класса
<?php
final class BaseClass <
public function test () <
echo «Вызван метод BaseClass::test()\n» ;
>
// В данном случае неважно, укажете ли вы этот метод как final или нет
final public function moreTesting () <
echo «BaseClass::moreTesting() called\n» ;
>
>
class ChildClass extends BaseClass <
>
// Выполнение заканчивается фатальной ошибкой: Class ChildClass may not inherit from final class (BaseClass)
// (Класс ChildClass не может быть унаследован от окончательного класса (BaseClass))
?>
Замечание: Свойства не могут быть объявлены окончательными, только классы и методы.
Final class означает что php
Note for Java developers: the ‘final’ keyword is not used for class constants in PHP. We use the keyword ‘const’.
Note that you cannot ovverride final methods even if they are defined as private in parent class.
Thus, the following example:
<?php
class parentClass <
final private function someMethod () < >
>
class childClass extends parentClass <
private function someMethod () < >
>
?>
dies with error «Fatal error: Cannot override final method parentClass::someMethod() in ***.php on line 7»
Such behaviour looks slight unexpected because in child class we cannot know, which private methods exists in a parent class and vice versa.
So, remember that if you defined a private final method, you cannot place method with the same name in child class.
@thomas at somewhere dot com
The ‘final’ keyword is extremely useful. Inheritance is also useful, but can be abused and becomes problematic in large applications. If you ever come across a finalized class or method that you wish to extend, write a decorator instead.
<?php
final class Foo
<
public method doFoo ()
<
// do something useful and return a result
>
>
final class FooDecorator
<
private $foo ;
public function __construct ( Foo $foo )
<
$this -> foo = $foo ;
>
public function doFoo ()
<
$result = $this -> foo -> doFoo ();
// . customize result .
return $result ;
>
>
?>
You can use final methods to replace class constants. The reason for this is you cannot unit test a class constant used in another class in isolation because you cannot mock a constant. Final methods allow you to have the same functionality as a constant while keeping your code loosely coupled.
Tight coupling example (bad to use constants):
class Foo implements FooInterface
<
const BAR = 1 ;
public function __construct ()
<
>
>
interface BazInterface
<
public function getFooBar ();
>
// This class cannot be unit tested in isolation because the actual class Foo must also be loaded to get the value of Foo::BAR
class Baz implements BazInterface
<
private $foo ;
public function __construct ( FooInterface $foo )
<
$this -> foo = $foo ;
>
public function getFooBar ()
<
return Foo :: BAR ;
>
$foo = new Foo ();
$baz = new Baz ( $foo );
$bar = $baz -> getFooBar ();
?>
Loose coupling example (eliminated constant usage):
<?php
interface FooInterface
<
public function bar ();
>
class Foo implements FooInterface
<
public function __construct ()
<
>
final public function bar ()
<
return 1 ;
>
>
interface BazInterface
<
public function getFooBar ();
>
// This class can be unit tested in isolation because class Foo does not need to be loaded by mocking FooInterface and calling the final bar method.
class Baz implements BazInterface
<
private $foo ;
public function __construct ( FooInterface $foo )
<
$this -> foo = $foo ;
>
public function getFooBar ()
<
return $this -> foo -> bar ();
>
$foo = new Foo ();
$baz = new Baz ( $foo );
$bar = $baz -> getFooBar ();
?>
imo good to know:
<?php
class BaseClass
<
protected static $var = ‘i belong to BaseClass’ ;
public static function test ()
<
echo ‘<hr>’ .
‘i am `’ . __METHOD__ . ‘()` and this is my var: `’ . self :: $var . ‘`<br>’ ;
>
public static function changeVar ( $val )
<
self :: $var = $val ;
echo ‘<hr>’ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`<br>’ ;
>
final public static function dontCopyMe ( $val )
<
self :: $var = $val ;
echo ‘<hr>’ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`<br>’ ;
>
>
class ChildClass extends BaseClass
<
protected static $var = ‘i belong to ChildClass’ ;
public static function test ()
<
echo ‘<hr>’ .
‘i am `’ . __METHOD__ . ‘()` and this is my var: `’ . self :: $var . ‘`<br>’ .
‘and this is my parent var: `’ . parent :: $var . ‘`’ ;
>
public static function changeVar ( $val )
<
self :: $var = $val ;
echo ‘<hr>’ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`<br>’ .
‘but the parent $var is still: `’ . parent :: $var . ‘`’ ;
>
public static function dontCopyMe ( $val ) // Fatal error: Cannot override final method BaseClass::dontCopyMe() in .
<
self :: $var = $val ;
echo ‘<hr>’ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`<br>’ ;
>
>
BaseClass :: test (); // i am `BaseClass::test()` and this is my var: `i belong to BaseClass`
ChildClass :: test (); // i am `ChildClass::test()` and this is my var: `i belong to ChildClass`
// and this is my parent var: `i belong to BaseClass`
ChildClass :: changeVar ( ‘something new’ ); // i am `ChildClass::changeVar()` and i just changed my $var to: `something new`
// but the parent $var is still: `i belong to BaseClass`
BaseClass :: changeVar ( ‘something different’ ); // i am `BaseClass::changeVar()` and i just changed my $var to: `something different`
BaseClass :: dontCopyMe ( ‘a text’ ); // i am `BaseClass::dontCopyMe()` and i just changed my $var to: `a text`
ChildClass :: dontCopyMe ( ‘a text’ ); // Fatal error: Cannot override final method BaseClass::dontCopyMe() in .
?>
<?php
class parentClass <
public function someMethod () < >
>
class childClass extends parentClass <
public final function someMethod () < >//override parent function
>
$class = new childClass ;
$class -> someMethod (); //call the override function in chield class
?>
The behaviour of FINAL is not as serious as you may think. A little explample:
<?php
class A <
final private function method ()<>
>
class B extends A <
private function method ()<>
>
?>
Normally you would expect some of the following will happen:
— An error that final and private keyword cannot be used together
— No error as the private visibility says, that a method/var/etc. is only visible within the same class
But what happens is PHP is a little curios: «Cannot override final method A::method()»
So its possible to deny method names in subclasses! Don’t know if this is a good behavior, but maybe its useful for your purpose.
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.
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’.
5 Answers 5
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 ?
- Preventing massive inheritance chain of doom
- Encouraging composition
- Force the developer to think about user public API
- Force the developer to shrink an object’s public API
- A final class can always be made extensible
- extends breaks encapsulation
- You don’t need that flexibility
- You are free to change the code
When to avoid final :
- There is an abstraction (interface) that the final class implements
- All of the public API of the final class is part of that interface
P.S. Thanks to @ocramius for great reading!
![]()
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.
-
Declaring a class as final prevents it from being subclassed—period; it’s the end of the line.
-
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.
-
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.
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.
In this example, none of them will be able to overridden the PageCount() method.
PHP final Keyword
Prevent inheritance of a class using the final keyword:
<?php
final class MyClass <
public $name = "John";
>
// This code will throw an error
class AnotherClass extends MyClass<>;
?>
Definition and Usage
The final keyword is used to prevent a class from being inherited and to prevent inherited method from being overridden.
Related Pages
Read more about inheritance in our PHP OOP — Inheritance Tutorial.

COLOR PICKER


Report Error
If you want to report an error, or if you want to make a suggestion, do not hesitate to send us an e-mail:
Thank You For Helping Us!
Your message has been sent to W3Schools.
Top Tutorials
Top References
Top Examples
Get Certified
W3Schools is optimized for learning and training. Examples might be simplified to improve reading and learning. Tutorials, references, and examples are constantly reviewed to avoid errors, but we cannot warrant full correctness of all content. While using W3Schools, you agree to have read and accepted our terms of use, cookie and privacy policy.