-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();,这是合理的,因为$this现在B而不是A......但是我不知道如何躲避它。

顺便说一句,我知道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不需要继承自A. 我们仍然希望B能够“添加东西”,所以它会保留一个名为addSomething(). 由于我们不想addSomething在两个类中复制主体,我们可以将B其委托给调用A时的实例B::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。渲染和管理列表实际上是两个不同的问题,所以让我们把它分开。首先,我们将addSomething进入B. 然后我们意识到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 回答