web-dev-qa-db-ja.com

parent :: parent in PHP

私は親にアクセスする方法を探します、親を呼び出さずにクラスの親関数...うーん、ちょっと奇妙な説明に聞こえるので、例を挙げます:

class myclass
{
  public function test() { return 'level 1'; }
}
class myclass2 extends myclass
{
  public function test() { return parent::test() . '-level 2'; }
}
class myclass3 extends myclass2
{
  public function test() { return parent::test() . '-level 3'; }
}
$example = new myclass3();
echo $example->test(); // should display "level 1-level 2-level 3"

「レベル1-レベル3」を表示して、そのようなことをしたいと思います。

class myclass3 extends myclass2
{
  public function test() { return parent::parent::test() . '-level 3'; }
}

私がこれをどのようにできるか考えていますか? (フレームワークの一部であるmyclassとmyclass2を編集することはできません...)

40
Alexandre

シンプルなソリューション。ルートオブジェクトmyclassを直接使用します。

class myclass3 extends myclass2
{
  public function test() { return myclass::test() . '-level 3'; }
}

より一般的なアプローチが必要な場合は、 outis answer をご覧ください。

56
PiTheNumber

get_parent_class

function get_grandparent_class($thing) {
    if (is_object($thing)) {
        $thing = get_class($thing);
    }
    return get_parent_class(get_parent_class($thing));
}

class myclass3 extends myclass2 {
    public function test() {
      $grandparent = get_grandparent_class($this);
      return $grandparent::test() . '-level 3'; 
    }
}

または、 reflection :を使用できます

function get_grandparent_class($thing) {
    if (is_object($thing)) {
        $thing = get_class($thing);
    }
    $class = new ReflectionClass($thing);
    return $class->getParentClass()->getParentClass()->getName();
}

ただし、達成しようとしている内容によっては、良いアイデアとは言えません。

22
outis

たぶん、myclass3のメンバーオブジェクトとしてmyclass2を追加し、次のようなコードを試してください。

class myclass3{
myclass2 obj2;
public function test() { return $obj2->callParentTest() . '-level3';}
}
4
LostMohican

いいえ、これは不可能です。残念ながら、元のクラスを直接参照することはできません。selfまたはparentのみです。

3

クラス1でテスト関数を直接使用する場合は、クラス1から拡張する必要があります。ポリモーフィズムについて検索してください。

parent::parent::parent::parent "class5があるとき??

テストメソッドにlevelパラメーターを追加できると思います。最初に確認してください。

<?php
    class myclass
    {
        public function test($level) 
        { 
            return 'level 1'; 
        }
    }
    class myclass2 extends myclass
    {
        public function test($level) 
        { 

            return $level >= 2 ? parent::test($level) . '-level 2' : parent::test($level); 
        }
    }
    class myclass3 extends myclass2
    {
        public function test() 
        { 
            return parent::test(1) . '-level 3';
        }
    }
    $example = new myclass3();
    echo $example->test(); // should display "level 1-level 3"

親を連鎖させることはできません。代わりに、親クラスに$ thisを返すだけのGetParent()メソッドを作成します。

2
Eric Herlitz

私のアプローチ:コードがある場合:

class A {
    protected function method () {
        var_dump('A -> method');
    }
}

class B extends A {
    protected function method () {
        var_dump('B -> method');
    }
}

class C extends B {
    protected function method () {
        var_dump('C -> method');
    }
}

class C call method from class A (だがしかし class B)コードにリファクタリングします:

<?php

class A {
    protected function method () {
        $this->methodA();
    }

    protected function methodA () {
        var_dump('A -> method');
    }
}

class B extends A {
    protected function method () {
        var_dump('B -> method');
    }
}

class C extends B {
    protected function method () {
        $this->methodA();
    }
}
1
W92

場合によっては、おそらくルートのメソッドを完全にオーバーライドできます。つまり、親の親のコードを呼び出す代わりに、親の親のメソッドコードをコピーして追加できます。

1
Luca Reghellin

ルートオブジェクトを取得する演算子はありません。私はこのようなことをします:

class myclass
{
  public function getRoot() { return __CLASS__; }
  public function test() { return 'level 1'; }
}
class myclass2 extends myclass
{
  public function getRoot() { return parent::getRoot(); }
}
class myclass3 extends myclass2
{
  public function getRoot() { return parent::getRoot(); }
  public function test() {
    $grandparent = self::getRoot();
    return $grandparent::test() . '-level 3';
  }
}
$example = new myclass3();
echo $example->test(); // should display "level 1-level 2-level 3"
1
PiTheNumber