web-dev-qa-db-ja.com

PHPでFinalを使用する場合

Finalクラスの定義が何であるかは知っていますが、finalが本当に必要な方法と時期を知りたいです。

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

正しく理解できれば、「final」で「Foo」を拡張できます。

誰が「いつ」「いつ」を使用すべきかを説明できますか?言い換えれば、クラスを拡張すべきでない理由はありますか?

たとえば、クラス「Bar」とクラス「Foo」にいくつかの機能が欠けている場合、「Bar」を拡張するクラスを作成するとよいでしょう。

50
Inga Johansson

一般的な使い方としては、クラスを「最終」にすることをお勧めします。意味のあるユースケースがいくつかあります:複雑なAPI /フレームワークを設計し、フレームワークのユーザーが制御したい機能の部分のみをオーバーライドできるようにしたい場合は、あなたにとって意味があるかもしれませんこの可能性を制限し、特定の基本クラスを最終的にします。

例えば「整数」クラスがある場合、フレームワークのユーザーがクラス内の「add(...)」メソッドをオーバーライドできるようにするために、そのfinalを作成するのが理にかなっているかもしれません。

18
mhanisch

"いつクラスfinalを宣言するか" についての素晴らしい記事があります。それからいくつかの引用:

TL; DR:インターフェイスを実装し、他のパブリックメソッドが定義されていない場合、クラスを常にfinalにします

finalを使用する必要があるのはなぜですか?

  1. Doomの大量継承チェーンの防止
  2. 有望な組成
  3. 開発者にユーザーのパブリックAPIについて考えるように強制する
  4. 開発者にオブジェクトのパブリックAPIを縮小させる
  5. finalクラスは常に拡張可能にすることができます
  6. extendsはカプセル化を解除します
  7. その柔軟性は必要ありません
  8. コードを自由に変更できます

finalを回避する場合:

最終クラスは、次の前提の下でのみ効果的に機能します。

  1. Finalクラスが実装する抽象化(インターフェイス)があります
  2. 最終クラスのパブリックAPIはすべて、そのインターフェイスの一部です

これらの2つの前提条件のいずれかが欠落している場合、コードは本当に抽象化に依存していないため、クラスを拡張可能にする時点に達する可能性があります。

追伸素晴らしい読書をしてくれた@ocramiusに感謝します!

45
Nikita U.

その理由は次のとおりです。

  1. クラスをfinalとして宣言すると、サブクラス化できなくなります(期間)。行末です。

  2. クラス内のすべてのメソッドをfinalとして宣言すると、サブクラスを作成できます。サブクラスは親クラスのメソッドにアクセスできますが、オーバーライドすることはできません。サブクラスは、独自の追加のメソッドを定義できます。

  3. 最後のキーワードは、オーバーライドする機能のみを制御し、プライベート可視性修飾子と混同しないでください。プライベートメソッドは、他のクラスからはアクセスできません。最後の1つができます。

-本の68ページから引用PHPオブジェクト指向ソリューション by David Powers

例えば:

_final childClassname extends ParentsClassname {
    // class definition omitted
}
_

これは、すべてのメソッドとプロパティを含むクラス全体をカバーします。 childClassnameから子クラスを作成しようとすると、致命的なエラーが発生するようになりました。ただし、クラスのサブクラス化を許可する必要があるが、特定のメソッドがオーバーライドされないようにする必要がある場合、finalキーワードはメソッド定義の前に配置されます。

_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()メソッドをオーバーライドできません。

11
li bing zhao

最終クラスは拡張できないものです http://www.php.net/manual/en/language.oop5.final.php

オーバーライドしたくないメソッドがクラスに含まれている場合に使用します。これは、doを実行するとアプリケーションが何らかの形で破損する可能性があるためです。

6
Matt Asbury