3

在这一点上,假设我有一个这样的课程:

class Sentence {
  __construct($content) {
    $this->content = $content;
  }
  public function grab_word($num) {
    $words = explode(" ", $this->content);
    return $words[$num+1];
  }
}

所以给定的接口允许我创建一个new Sentence,然后我可以调用grab_word()类方法来获取句子中的一个单词:

$sentence = new Sentence("Lorem ipsum dolor sit amet");
echo $sentence->grab_word(2);

但是,我想做的是添加另一个链式类方法,让我能够将这个词大写。

$sentence->grab_word(2); # -> ipsum
$sentence->grab_word(2)->caps(); # -> IPSUM

显然,这是行不通的,因为链式方法需要对象继承。如果我要创建并链接该函数 - 由于返回不是继承的对象 caps(),它将返回一个错误。Sentence

总而言之,我的问题是如何实现可选地链接这些方法的能力,但在需要时仍返回非对象(如在我的输出示例中)。

4

3 回答 3

4
class Sentence {
  function __construct($content) {
    $this->content = $content;
  }
  public function grab_word($num) {
    $words = explode(" ", $this->content);
    return new Sentence($words[$num+1]);
  }
  public function caps() {
    return new Sentence(strtoupper($this->content));
  }
  function __toString(){
      return $this->content;
  }
}

但是,具有 __toString 方法的对象与字符串并不完全兼容。它仍然是一个对象,但是,当在字符串上下文中显式使用时,它将转换为字符串。

于 2012-06-09T00:26:04.687 回答
3

从广义上讲,您要问的是不可能的。为什么不总是返回有时需要链接方法调用的对象?只要回来new Word($words[ ... ]),你就会处于一个更好的位置。

现在,当我说“广义上”时,您可以做一些事情来调用不同的方法,这些方法可能存在于不同的类中。您可以使用__call()来实现类似于 ruby​​ 的 mixin 的东西,尽管确实很差。 __call()将只查看被调用的方法名称,然后迭代可能的目标列表并查看它们是否响应该方法,然后将调用委托给该对象(或引发异常)。

PS:这个问题与继承无关。方法链接需要返回一个对象,而不仅仅是实现继承层次结构。当然,你可以 return $this,这是有道理的,但通常你会返回另一个对象。

于 2012-06-09T00:22:22.147 回答
2

在某些将 String 视为对象的语言中,您想要做的事情是相当合乎逻辑的。PHP 受到 Perl 和 C 的启发,并且在设计上“字符串”不是对象。

您可以使其成为将其封装到类中的对象:

class Word {
    private $content;
    function __construct($content){
        $this->content=$content;
    }
    function __toString(){
        return $this->content;
    }
    function caps(){
        strtoupper($this->content);
        return $this;
    }
}

class Sentence {
    function grab_word($num)
        $words = explode(" ", $this->content);
        return new Word($words[$num+1]);
    }
}

您还应该查看@chris 的答案,因为它为您提供了略有不同的实现。我建议您不要在没有显式克隆的情况下创建新的对象实例,因为这会浪费资源,而且 PHP 的设计侧重于服务器的快速准确响应。

于 2012-06-09T00:36:21.007 回答