【问题标题】:How to retrieve ancestor while chaining instances of classes如何在链接类实例时检索祖先
【发布时间】:2016-07-10 12:40:30
【问题描述】:

我正在用 PHP 开发一个应用程序,其中(类似 jQuery 的)链接方法风格非常方便。我不是在谈论继承链,而是关于“嵌入”彼此的类实例的分类。现在我想知道如何从较低级别引用较高级别的实例。

这听起来很抽象,所以让我举个例子。假设我想用 PHP 写一本书(proze)(只是为了争论)。如果我可以这样编码,那就很方便了

$myBestseller = new Book();

$myBestseller
  ->setAuthor("Jean-Saul Partre")
   ->addChapter()
    ->addParagraph("How the Rabit lost its wings.")
        ->addWords("On a beautiful wintes day, the rabit flew over the … ") 
        ->addWords("Bla bla") 
        ->addWords("Bla bla");

到目前为止,我得到了它的工作。 (我应该包含实际的类定义吗?)如果我想引用层次结构中更高对象的属性怎么办?假设我想在章节标题中包含作者姓名:

    $myBestseller = new Book();

    $myBestseller
      ->setAuthor("Jean-Saul Partre")
       ->addChapter()
        ->addParagrapWithAuthor("How "," fell out of the window.");
            ->addWords("Bla bla")
            ->addWords("Bla bla")
            ->addWords("Bla bla")

    var_dump($myBestseller);

让我们在这里也添加章节类定义:

class Chapter{
  private $_paragraphs = array();

  public function addParagraph($title){
    return $this->_pages[] = new Paragraph($title);
  }

  public function addParagrapWithAuthor($prefix, $suffix){
    $author = "Ideo Gram";
    return $this->_pages[] = new Paragraph($prefix.$author.$suffix);
  }
}

所以,我想使用本书作者的定义而不是 $author = "Ideo Gram"。带有此代码的标题将是

Ideo Gram 是如何从窗户掉出来的

相反,我想说

Jean-Saul Patre 是如何从窗户掉下来的

这可以吗?到目前为止,我发现的唯一解决方案是在“桌子底下”传递对后代的引用,但这感觉就像污染了类。

也许答案很直接,但我找不到。我可能不知道正确的条款。 ::parent,例如,适用于扩展类。

【问题讨论】:

  • 如果您需要实体之间的双向链接,请在作者中保留对本书的引用(您似乎已经从书中获得了对作者的引用)。这是唯一的方法。如果您自己不定义这种关系,这些实体将彼此完全无关。
  • 我很好奇在这种情况下是否也会对使用可变参数函数感兴趣。让我知道你的想法:en.wikipedia.org/wiki/Variadic_function
  • @aguertin 有趣的想法,谢谢。您是否建议通过此 Variadiac 函数传递“祖先”?像 addCharacter('æ',$parent, $grandparent, $greatgrandparent, $greatgreatparent)?我很惊讶它可以用 PHP 完成:php.net/manual/en/…
  • @aguertin :好主意。是的,它可以工作,但我认为在这个用例中不应该这样做。如果一章没有链接到一本书,则该章不能存在,因此该书可以是构造函数的参数(作为强制依赖项)。对我来说,这似乎是最干净的解决方案。这样做没有任何错误或肮脏。

标签: php oop chaining


【解决方案1】:

没有魔法。如果您需要 2 个实体之间的双向关系,则它们需要相互引用。

所以你的方法addChapter 可以做到这一点:

public function addChapter() {
    return $this->chapters[] = new Chapter($this);
}

所以你的章节变成了:

class Chapter {

    protected $book;

    public function __construct(Book $book) {
        $this->book = $book;
    }

    ....

    public function addParagrapWithAuthor($prefix, $suffix){
        $author = $this->book->getAuthor()->getFullName();
        return $this->_pages[] = new Paragraph($prefix.$author.$suffix);
    }
}

【讨论】:

  • 很好的答案,谢谢。这就是我所说的“从桌子底下经过”的意思。在我的应用程序中,这可能意味着将对“根”对象的引用传递 5 层深。从您的回答和示例中,我了解到这是完全可以接受的。而且没有什么神奇的方法可以让后代知道它的祖先:)
  • 我不认为它像你说的那样“在桌子底下”。你可以把它看成一个章节如果不属于一本书就无法生存。
  • 确实不行:)
猜你喜欢
  • 1970-01-01
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多