5

メソッドを再定義し、親のバージョンではなく、祖先のバージョンを呼び出したいと考えています。

以下に短い例を示します。

// This class is autogenerated and I am not supposed to modify it.
class myParent extends myGrandparent {

  function doSomething() {
    doA();
    doB();
    doC();
    parent::doSomething();
  }

}

// Here is my code
class myClass extends myParent {

  function doSomething() {
    // doA();    // I don't want to do A anymore.
    // doB();    // Neither B.
    doC();       // But I want to keep doing C.
    parent::doSomething();      // OOPS!!  This does A and B (and C again)!
  }

}

myParent のメソッドではなく、myGrandparent のメソッドを直接呼び出すにはどうすればよいですか?

4

4 に答える 4

4

「これを行うことはできません」という議論には同意しません-これはReflectionで行うことができます。

次のクラス構造を検討してください。

class A { 
    function foo() { 
        echo 'A'; 
    }
}

class B extends A { 
    function foo() { 
        parent::foo();  
        echo 'B'; 
    }
}

class C extends B { 
    function foo() { 
        parent::foo();
        echo 'C'; 
    }
}

これで初期化すると:

$o = new C;
$o->foo();

印刷されます(予想どおり、このデモで見られます):

ABC

課題は、出力から を削除しB、実質的に と のみを実行することAです。そこで、Reflection にドロップしてのメソッドを取得し、それをのオブジェクトで呼び出します。について、次の代替定義を考えてみましょう。foo()Cfoo()Afoo()CC

class C extends B { 
    function foo() { 
        $ref = new ReflectionClass( $this);
        $parent = $ref->getParentClass()->getParentClass();
        $parent->getMethod( 'foo')->invoke( $this);
        echo 'C'; 
    }
}

これで、出力としてのみ取得できます (このデモで見られるように):

AC

これが「良い習慣」であるかどうかは、OP次第です。Bの関数の実装を「スキップ」して、孫クラスから祖父母関数を呼び出すことができることを実証したと思います。

于 2012-09-05T18:06:50.870 に答える
2

ユースケースが何であるかはわかりませんが、質問/問題を誤解していない限り(かなり可能性があります)、任意の祖先(パブリックまたは保護)メソッドを完全に呼び出すことができます。オーバーライドされている場合でも、任意の祖先メンバー属性 (public または protected) の値。たとえば、クラス階層では次のようになります。

Papa > Mama > Baby > Infant、メソッドsayWhat()とインスタンス変数$elの両方が各子孫クラスでオーバーライドされる場合、Infant から祖先の sayWhat メソッドを呼び出して、別の祖先のデフォルト属性値にアクセスできます。

class Papa {
  protected $el = 'PapaEl';
  protected function sayWhat($className = null) {
    if (!$className) {
      $className = get_class($this);
    }
    $classVars = get_class_vars($className);
    $localEl = $classVars['el'];
    echo "<h2>What is PAPA!. El: [$localEl]</h2>";
  }
}

class Mama extends Papa {
  protected $el = 'MamaEl';
  protected function sayWhat() {
    echo "<h2>What is MAMA! El: [$this->el]</h2>";
  }
}

class Baby extends Mama {
  protected $el = 'BabyEl';
  protected function sayWhat() {
    echo "<h2>What is Lil' Baby!! El: [$this->el]</h2>";
  }
}

class Infant extends Baby {
  protected $el = 'InfantEl';
  protected function sayWhat($className) {
    Papa::sayWhat($className);
  }

  public function mySayWhat($className) {
    $this->sayWhat($className);
  }
}
$i = new Infant();
$i->mySayWhat('Mama');

出力:

パパとは!エル:[ママエル]

それがどのような価値があるのか​​ はわかりませんが、誰かが要件を持っている場合、それは非常に実行可能に思えます...

于 2014-06-08T17:21:24.330 に答える
0

答えはノーです、できません。子はメソッドの親機能を再宣言し、それを完全にオーバーライドします。

parent ::キーワードをチェーンして「祖父母」クラスに戻すことはできないため、静的メソッドが必要になると思います。そのため、parent :: parent :: foo()は機能しません。

于 2012-09-05T17:54:03.743 に答える
0

あなたは本当にできません。myGrandParent から直接拡張するか、MyParent のロジックを作り直して myGrandParents メソッドへの「パススルー」アクセスを提供する必要があります。たとえば、次のように myParent でメソッドを作成できます。

function doSomethingGrandparent() {
    parent::doSomething();
}

次に、 myClass の doSomething メソッドを次のように変更します。

function doSomething() {
    parent::doSomethingGrandparent();
}
于 2012-09-05T17:48:13.433 に答える