-3

基本的なクラスを見てみましょう:

class A
{
   public function renderSomethingRecursive()
   {
      //this function can call itself
      self::renderSomethingRecursive(); // ERROR!!!!
   }

   abstract public function addSomething (value);
}

class B extends A
{
   public function renderSomethingRecursive()
   {
      throw new Exception ('This time this method must not be called!');
   }

   public function addSomething (value)
   {
      //something, something, something....
      parent::renderSomethingRecursive();
   }
}

$obj = new B();
$obj->addSomething(....);

これを行うと、B::renderSomethingRecursive()まだ呼び出されますが、これは望ましくありません...A:renderSomethingRecursive()メソッドではなく、self::renderSomethingRecursive(); // ERROR!!!!行呼び出しで、これは今ではなく合理的です...しかし、それをかわす方法がわかりません。B::renderSomethingRecursive(); A::renderSomethingRecursive();$thisBA

ところで、B::renderSomethingRecursive()メソッドを削除する必要があることはわかっていますが、誤って呼び出してはならないという通知として保持したかったのです。これを利用できないようにするために「プライベート」にしたかったのですが、私たちが知っているように、それは不可能です:)

何か案は?

4

2 に答える 2

2

B呼び出されたくないのに、なぜメソッドを定義したのですか。定義しないでください。PHP が呼び出すことができるメソッドは 1 つだけです。そうすれば、 を使用する必要はありません。parent::theMethod簡単に呼び出すことができます。this->theMethod();

Abstract class A
{
   public function renderSomethingRecursive()
   {
      $this->renderSomethingRecursive(); // no need for self::, that's for static calls
   }

   abstract public function addSomething (value);
}

class B extends A
{
   public function addSomething (value)
   {
      $this->renderSomethingRecursive();//calls the abstract method as though it were defined in class B
   }
}

それだけです、本当に

于 2012-10-28T17:32:38.593 に答える
2

継承ではなく構成を優先するようにリファクタリングしてみませんか? 「何かを追加する」と「再帰的な何か」を別々の関心事に分割し始めると、非常にうまく連携する、より小さくて理解しやすいクラスが得られることに気付くでしょう。

の呼び出し元Bが呼び出せないようにrenderSomethingRecursive()するため、関数をクラスから完全に削除します。また、継承を解除します。Bから継承する必要はありませんABという関数を保持するように、「何かを追加」できるようにしたいのですaddSomething()addSomething両方のクラスでの本体を複製したくないので、呼び出されるたびBに のインスタンスに委譲することができます。AB::addSomething

abstract class A
{
   public function renderSomethingRecursive()
   {
      // this function can call itself
      self::renderSomethingRecursive();
   }

   abstract function addSomething ($value) {

}

class AA extends A
{
   public function addSomething($value)
   {
      // something, something, something....
      self::renderSomethingRecursive();
   }
}


class B
{
   private $a;
   public function __construct(A $a)
   {
      $this->a = $a;
   }

   public function addSomething ($value) {
      $this->a->addSomething($value);
   }
}

$obj = new B(new AA());
$obj->addSomething(....);

addSomethingこれはすでに改善されていますが、完了する前にこの重複を取り除くことができます。リストのレンダリングと管理は、実際には 2 つの異なる問題なので、分割してみましょう。まず、 に移動addSomethingBます。次に、renderSomethingRecursiveおそらく $data にもアクセスする必要があることに気付きました。そのデータに再びアクセスできるように、いくつかのパラメーターを追加できます。Aはもはや抽象的である必要はありませんが、Bの異なる実装がまだある場合は抽象的である可能性がありaddSomethingます。このようなものを残す必要があります...

class A
{
   public function renderSomethingRecursive($data)
   {
      // this function can call itself
      self::renderSomethingRecursive($data);
   }     
}

class B
{
   private $a;
   private $data;
   public function __construct(A $a)
   {
      $this->a = $a;
   }

   public function addSomething ($value) {
      // something, something, something....
      // append to $this->data probably
      $this->a->renderSomethingRecursive($this->data);
   }
}

$obj = new B(new AA());
$obj->addSomething(....);
于 2012-10-28T17:35:28.643 に答える