Подтвердить что ты не робот

Когда использовать Final в PHP?

Я знаю, что такое определение класса Final, но я хочу знать, как и когда окончательный действительно нужен.

<?php
final class Foo extends Bar
{
   public function()
   {
     echo 'John Doe';
   }
}

Если я правильно понимаю, "final" позволяет ему расширять "Foo".

Может ли кто-нибудь объяснить, когда и зачем использовать "final"? Другими словами, есть ли причина, по которой класс не должен быть расширен?

Если, например, для класса "Bar" и класса "Foo" отсутствуют некоторые функции, было бы неплохо создать класс, который расширяет "Bar".

4b9b3361

Ответ 1

Для общего использования я бы рекомендовал не делать класс "final". Там могут быть некоторые варианты использования, когда это имеет смысл: если вы разрабатываете сложный API/фреймворк и хотите, чтобы пользователи вашей инфраструктуры могли переопределять только те части функциональности, которые вы хотите, чтобы они контролировали, может иметь смысл для вас ограничить эту возможность и сделать определенные базовые классы окончательными.

например. если у вас есть класс "Integer", может возникнуть смысл сделать это окончательным для того, чтобы пользователи вашей формы фрейма переопределили, скажем, метод "добавить (...)" в ваш класс.

Ответ 2

Есть хорошая статья о "Когда объявлять классы final" . Несколько цитат из него:

TL; DR: всегда создавайте классы final, если они реализуют интерфейс, и не определены другие общедоступные методы

Почему мне нужно использовать final?

  • Предотвращение массивной цепи наследования doom
  • Поощрение композиции
  • Помогите разработчику подумать об пользовательском общедоступном API
  • Заставить разработчика сжать объект public API
  • Класс final всегда можно сделать расширяемым
  • extends прерывает инкапсуляцию
  • Вам не нужна гибкость.
  • Вы можете изменить код

Когда следует избегать final:

Конечные классы работают эффективно только при следующих предположениях:

  • Существует абстракция (интерфейс), которую последний класс реализует
  • Все публичные API конечного класса являются частью этого интерфейса.

Если одна из этих двух предварительных условий отсутствует, вы, вероятно, достигнете момента времени, когда вы сделаете класс расширяемым, так как ваш код действительно не полагается на абстракции.

P.S. Спасибо @ocramius за отличное чтение!

Ответ 3

Причина:

  • Объявление класса как окончательного не позволяет ему быть подклассом-периодом; его конец строки.

  • Объявление каждого метода в классе как final позволяет создавать подклассы, которые имеют доступ к методам родительских классов, но не могут их переопределить. Подклассы могут определять дополнительные собственные методы.

  • Конечное ключевое слово управляет только возможностью переопределения и не должно путаться с частным модификатором видимости. К закрытому методу нельзя получить доступ к какому-либо другому классу; окончательный вариант. (Цитаты из книги PHPObjectOrientedSolutions Page 68);

например:

final childClassname extends ParentsClassname {
    // class definition omitted
}

Это охватывает весь класс, включая все его методы и свойства. Любая попытка создать дочерний класс из childClassname приведет к фатальной ошибке. Но, если вам нужно позволить классу быть подклассом, но исключить переопределение определенного метода, последнее ключевое слово идет перед определением метода.

class childClassname extends parentClassname { 
    protected $numPages;

    public function __construct($autor, $pages) {
        $this->_autor = $autor;
        $this->numPages = $pages;
    }

    final public function PageCount() { 
        return $this->numPages; 
    }
}

В этом примере ни один из них не сможет переопределить метод PageCount().

Ответ 4

Последний класс - это тот, который не может быть расширен http://www.php.net/manual/en/language.oop5.final.php

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