Search code examples
phpoopinheritancechaining

OOP Method chaining optional return


At this point, let's say I have a class like so:

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

So the interface given would allow me to create a new Sentence, and then I could call the grab_word() class method to fetch a word in the sentence:

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

However, what I'd like to do is add another chained class method, giving me the ability to capitalize this word.

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

Clearly, this won't work because chained methods require object inheritance. If I were to create caps() and chain that function - it would return an error due to the return not being the inherited Sentence object.

To sum it up, my question is how to I achieve the ability to chain these methods optionally, but still return a non-object whenever needed (like in my output example).


Solution

  • Broadly speaking, what you're asking is not possible. Why don't you just always return the object you sometimes need to chain method calls onto? Just return new Word($words[ ... ]) and you'll be in a better position.

    Now, when I say "broadly speaking", there are things you can do to make it possible to call different methods, that may live in different classes. You can make use of __call() to implement something similar to ruby's mixins, though really quite inferior. __call() will simply look at the method name that was invoked, then iterate a list of possible targets and see if they respond to that method, before delegating the invocation to that object (or raising an exception).

    PS: This question hasn't got anything to do with inheritance. Method chaining requires returning an object, not just implementing an inheritance hierarchy. Of course, you may return $this, where that makes sense, but usually you return another object.