PHPで親メソッドを呼び出す複数の方法


90

最初は、コンストラクターの両方のメソッド呼び出しが機能する理由に戸惑いましたが、今では理解できたと思います。拡張クラスは、クラス自体で宣言されているかのように親のメソッドを継承し、メソッドは親に存在するため、両方が機能するはずです。

ここで、メソッドを(parentまたはを介して)呼び出すための好ましい方法(つまり、ベストプラクティス)があるthisかどうか、これらが同じコードを実行するための本当に同じ方法であるかどうか、または1つを使用するときに注意事項があるかどうか疑問に思っています。もう1つ。

申し訳ありませんが、私はおそらくこれを考えすぎています。

abstract class Animal {

    function get_species() {

        echo "test";

    }

}

class Dog extends Animal {

    function __construct(){

        $this->get_species();
        parent::get_species();

    }

}

$spike = new Dog;

回答:


120

メソッドが親クラスに存在するサブクラスのメソッドを呼び出すシナリオは3つあります(私は考えることができます)。

  1. メソッドはサブクラスによって上書きされず、親にのみ存在します。

    これはあなたの例と同じであり、一般的には使用$this -> get_species(); する方が良いです。この場合、2つは事実上同じですが、メソッドはサブクラスに継承されているため、区別する理由はありません。を使用$thisすることにより、継承されたメソッドとローカルで宣言されたメソッドの間で一貫性を保つことができます。

  2. メソッドはサブクラスによって上書きされ、親から完全に一意のロジックを持ちます。

    この場合、$this -> get_species();親のバージョンのメソッドを実行したくないので、明らかに使用する必要があります。繰り返しますが、一貫してを使用$thisすることにより、このケースと最初のケースの違いについて心配する必要はありません。

  3. メソッドは親クラスを拡張し、親メソッドが達成するものに追加します。

    この場合でも`$this -> get_species();、サブクラスの他のメソッドからメソッドを呼び出すときに使用する必要があります。親メソッドを呼び出す1つの場所は、親メソッドを上書きしているメソッドからです。例:

    abstract class Animal {
    
        function get_species() {
    
            echo "I am an animal.";
    
        }
    
     }
    
     class Dog extends Animal {
    
         function __construct(){
    
             $this->get_species();
         }
    
         function get_species(){
    
             parent::get_species();
             echo "More specifically, I am a dog.";
         }
    }
    

オーバーライドするメソッドのすぐ外で親メソッドを呼び出す必要があると私が想像できる唯一のシナリオは、2つの異なることを行い、ローカルではなく親のバージョンのメソッドが必要であることがわかっている場合です。これは当てはまらないはずですが、それ自体が存在する場合、これにアプローチするクリーンな方法get_parentSpecies()は、親メソッドを呼び出すだけのような名前で新しいメソッドを作成することです。

function get_parentSpecies(){

     parent::get_species();
}

繰り返しになりますが、これによりすべてが適切で一貫性が保たれ、親メソッドに依存するのではなく、ローカルメソッドへの変更/変更が可能になります。


「拡張」せずにどうすればよいですか?クラス「human」内にいくつかのクラス「leg」があるようですが、親の「human」機能は必要ないため、実際に拡張する必要はありません。さて、$leg = new leg()内部を作成した場合human、レッグインスタンスの内部から人間の関数をどのように呼び出すのでしょう$legか?
user151496 2016年

@ user151496脚は人間のサブクラスではありません。人間にはたくさんの足がありますが、足は人間の一種ではありません。したがって、脚は人間ではないため、人間から継承する脚のクラスを持つべきではありません。
カブトムシ

LegをLeggyのインターフェースを持つクラスにしますか?それとも、HumanクラスにLeggyを実装させるだけですか?脚が人間だけのものではなく、人間の脚が独特の人間であり、人間の一般的な特性であることをどのように最もよく定義できますか?
アンソニー

2
paamayimnekudotayimは少し紛らわしいです。一見、静的メソッドを呼び出しているように見えます。代わりにparent-> get_species()にする必要がありました
peterchaula 2018年

同意しました。静的呼び出しは、多くの点で非常に混乱します。いつかこれを更新する必要があります。
アンソニー

5

質問を誤解しない限り、サブクラス(この場合はdog)はメソッドを拡張するため、そのメソッドを上書きする可能性があるため、ほとんどの場合$ this-> get_speciesを使用します。クラスdogがメソッドを再定義しない場合、両方の方法は機能的に同等ですが、将来のある時点で、dogのget_speciesメソッドで「dog」を出力する必要がある場合は、すべてのコードに戻って、それを変更。

$ thisを使用すると、実際には作成したオブジェクトの一部であるため、親クラスを使用している間は常に最新の状態になります(使用されているプロパティがオブジェクトの存続期間中に何らかの形で変更された場合)。静的クラスメソッドを呼び出しています。


これは、メソッドをオーバーライドしたい場合に$ thisを使用することの良い点です。ありがとう
ジェリー2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.