Что делает ключевое слово final php
Перейти к содержимому

Что делает ключевое слово final php

  • автор:

Что делает ключевое слово final php

Note for Java developers: the ‘final’ keyword is not used for class constants in PHP. We use the keyword ‘const’.

16 years ago

Note that you cannot ovverride final methods even if they are defined as private in parent class.
Thus, the following example:
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.

9 years ago

@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.

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 ;
>
>
?>

14 years ago

The use of final keyword is just like that occurs in Java
In java final has three uses
1) prevent class Inheritance
2) prevent method overriding or redifination of
method in subclass
3) and to declare constants
But the third point seems to be missing from the PHP
I guess, as i am a java developer Currently gaining competence in PHP

9 years ago

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):

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 ();
?>

9 years ago

imo good to know:
class BaseClass
protected static $var = ‘i belong to BaseClass’ ;

public static function test ()
echo ‘


‘ .
‘i am `’ . __METHOD__ . ‘()` and this is my var: `’ . self :: $var . ‘`
‘ ;
>
public static function changeVar ( $val )
self :: $var = $val ;
echo ‘


‘ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`
‘ ;
>
final public static function dontCopyMe ( $val )
self :: $var = $val ;
echo ‘


‘ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`
‘ ;
>
>

class ChildClass extends BaseClass
protected static $var = ‘i belong to ChildClass’ ;

public static function test ()
echo ‘


‘ .
‘i am `’ . __METHOD__ . ‘()` and this is my var: `’ . self :: $var . ‘`
‘ .
‘and this is my parent var: `’ . parent :: $var . ‘`’ ;
>
public static function changeVar ( $val )
self :: $var = $val ;
echo ‘


‘ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`
‘ .
‘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 ‘


‘ .
‘i am `’ . __METHOD__ . ‘()` and i just changed my $var to: `’ . self :: $var . ‘`
‘ ;
>
>

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 .
?>

15 years ago

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
?>

13 years ago

The behaviour of FINAL is not as serious as you may think. A little explample:
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.

13 years ago

«Note for Java developers: the ‘final’ keyword is not used for class constants in PHP. We use the keyword ‘const’.»

This is more or less true, regardless of the fact that constant (being defined at class level or not) in PHP are only scalar (int, string, etc) while in Java they may be pure object (ex: java.awat.Color.BLACK). The only possible solution of having such kind of constant is :

class Bar <. >
class Foo public static $FOOBAR ;

static function __init () static $init = false ;
if ( $init ) throw new Exception ( ‘Constants were already initialized’ );
self :: $FOOBAR = new Bar ();
$init = true ;
>
>
Foo :: __init ();
?>
That said, perhaps it is useless unless PHP automatically calls the __init() method.

However, one alternative that could be done in certain case is this :

function __autoload ( $className ) <
. require the file where the class is .
if ( interface_exists ( $className , false )) return;
if ( class_exists ( $className , false )) $rc = new ReflectionClass ( $className );
if (! $rc -> hasMethod ( ‘__init’ )) return;
$m = $rc -> getMethod ( ‘__init’ );
if (!( $m -> isStatic () && $m -> isPrivate ())) throw new Exception ( $className . ‘ __init() method must be private and static !’ );
>
$m -> invoke ( null );
return;
>
throw new Exception ( ‘Class or interface not found ‘ . $className );
>
?>

This can only work when one class is defined per file, since we are assured that __autoload() will be called to load the file containing the class.

test2.php:
class B public static $X ;
private static function __init () echo ‘B’ , «\n» ;
self :: $X = array( 1 , 2 );
>
>
class A public static $Y ;
private static function __init () echo ‘A’ , «\n» ;
self :: $Y = array( 3 , 4 );
>
>
?>
test.php:
function __autoload ( $n ) if ( $n == ‘A’ || $n == ‘B’ ) require ‘test2.php’ ;
. do our __init () trick .
>
var_dump ( B :: $X ); // shows B, then array(2) (1, 2)
var_dump ( A :: $Y ); // shows NULL.
?>

5 months ago

Class constants CAN be “finalised” since PHP8.1. To partly contradict to the most popular user contribution, that was written a long time ago, they were still absolutely right.

Ключевое слово «final»

PHP 5 представляет ключевое слово final, разместив которое перед объявлениями методов класса, можно предотвратить их переопределение в дочерних классах. Если же сам класс определяется с этим ключевым словом, то он не сможет быть унаследован.

Пример #1 Пример окончательных (final) методов

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) класса

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»

В предыдущих параграфах мы увидели, как можно наследовать один класс от другого. Мы также рассмотрели как перезаписать функцию класса-предка, и заменить ее исходное поведение. Однако, в некоторых случаях вам может потребоваться запретить наследоваться от класса или перезаписывать конкретную функцию. Это можно сделать с помощью ключевого слова «final» (окончательный), которое просто заставит PHP выбросить ошибку если кто-то попытается расширить финализированный класс или перезаписать функцию.

Финализированный класс может выглядить примерно так:

final class Animal

А класс с финализированной функцией — так:

class Animal < final public function Greet() < return "The final word!"; >>

Эти два способа можно комбинировать, а можно использовать по отдельности, как в примерах выше.

This article has been fully translated into the following languages:

Is your preferred language not on the list? Click here to help us translate this article into your language!

Что делает ключевое слово final php

Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Бесплатный Курс «Практика HTML5 и CSS3»

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Бесплатный тренинг «PHP для Создания Сайтов: Введение»

Что нужно знать для создания PHP-сайтов?

Ответ здесь. Только самое важное и полезное для начинающего веб-разработчика.

Узнайте, как создавать качественные сайты на PHP всего за 2 часа и 27 минут!

—> Бесплатный курс «Сайт-Визитка За 15 уроков»

Создайте свой сайт за 3 часа и 30 минут.

После просмотра данного видеокурса у Вас на компьютере будет готовый к использованию сайт, который Вы сделали сами.

Вам останется лишь наполнить его нужной информацией и изменить дизайн (по желанию).

—> Бесплатный курс «Основы HTML и CSS»

Изучите основы HTML и CSS менее чем за 4 часа.

После просмотра данного видеокурса Вы перестанете с ужасом смотреть на HTML-код и будете понимать, как он работает.

Вы сможете создать свои первые HTML-страницы и придать им нужный вид с помощью CSS.

Бесплатный курс «Сайт на WordPress»

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Бесплатный курс «Основы работы с JavaScript»

Хотите изучить JavaScript, но не знаете, как подступиться?

После прохождения видеокурса Вы освоите базовые моменты работы с JavaScript.

Развеются мифы о сложности работы с этим языком, и Вы будете готовы изучать JavaScript на более серьезном уровне.

*Наведите курсор мыши для приостановки прокрутки.

Ключевое слово final (завершенные классы и методы в PHP)

Наследование открывает большие возможности для широкого поля действий в пределах иерархии класса.

Вы можете переопределить класс или метод, чтобы вызов в клиентском методе приводил к совершенно разным результатам, в зависимости от типа объекта, переданного методу в качестве аргумента.

Но иногда код класса или метода необходимо «зафиксировать», если предполагается, что в дальнейшем он не должен изменяться.

Если вы создали необходимый уровень функциональности для класса и считаете, что его переопределение может только повредить отлаженной работе приложения, воспользуйтесь ключевым словом final.

Ключевое слово final позволяет положить конец наследованию. Для завершенного класса нельзя создать подкласс, а завершенный метод нельзя переопределить.

Давайте объявим класс завершенным:

final class Checkout < // тело класса >

Теперь давайте попробуем создать подкласс класса Checkout.

class IllegalCheckout extends Checkout < // тело класса >

Выполнение данного кода приведет к ошибке.

PHP Fatal error: class IllegalCheckout may not inherit from final class (Checkout) in .

По-русски это звучало бы примерно так: Класс IllegalCheckout не может быть унаследован от завершенного класса Checkout.

Мы можем несколько «смягчить» ситуацию, объявив завершенным только метод в классе Checkout, а не весь класс. Кстати, ключевое слово final должно стоять перед любыми другими модификаторами, такими как, например, protected или static.

Итак, объявляем завершенный метод:

class Checkout < final function totalize() < // тело функции >>

Теперь мы можем создать подкласс класса Checkout, однако любая попытка переопределить метод totalize() приведет к неустранимой ошибке.

class IllegalCheckout extends Checkout < final function totalize() < // тело функции >>

Выполнение кода, приведенного выше, даст нам такую ошибку:

// Fatal error: cannot override final method // Checkout::totalize() in .

Что в переводе на великий могучий означает: Нельзя переопределить завершенный метод сheckout::totalize().

В хорошем объектно-ориентированном коде во главу угла обычно ставится строго определенный интерфейс. Но за этим интерфейсом могут скрываться разные реализации. Разные классы или сочетания классов могут соответствовать общим интерфейсам, но при этом вести себя по-разному в разных ситуациях.

Объявляя класс или метод завершенным, мы тем самым ограничиваем его гибкость. В некоторых случаях это выгодно, и мы рассмотрим такие ситуации в других статьях позже на конкретных примерах.

Однако, прежде чем объявлять что-либо завершенным, следует хорошенько подумать: действительно ли нет таких ситуаций, в которых переопределение было бы полезным?

Конечно, мы можем передумать, но внести изменения впоследствии может быть нелегко, например, если вы распространяете библиотеку для совместного использования.

Отсюда простой вывод: будьте осторожны и четко осознавайте свои действия, если используете ключевое слово final.

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!

Смотрите также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *