Composition over inheritance: native support for "delegating" methods?
| From: | Rowan Collins | Date: | Sun, 21 Oct 2018 17:41:04 +0000 |
| Subject: | Composition over inheritance: native support for "delegating" methods? | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-103353@lists.php.net to get a copy of this message | ||
Hi,
I've been thinking about how the language could better support Composition patterns like Decorators and Proxies, using some simple syntax sugar not dissimilar to Traits.
Example problem:
The other day, I was writing a session handler which slightly modified the behaviour of one provided by a library. The library implementation was closed for inheritance (a final class accessed via a factory which handled configuration), so I wrote a Decorator class, which added a single method. Everything worked fine, using Composition over Inheritance. But...
In order for my Decorator class to implement the SessionHandlerInterface, I needed to write six stub functions, each of the form "function foo($bar) { return $this->delegatedHandler->foo($bar); }". With whitespace and docblocks, these amount to nearly 90 lines of code, as much as the actual custom code in the Decorator.
Possible solution:
Methods in a Decorator or Proxy which are delegated without any additional functionality can easily be generated programmatically, so could the language provide syntactic sugar to do this for you?
- To delegate to an instance held in a property, add the "delegate" keyword at the end of the property declaration, followed by a list of method names to generate, e.g. "private Foo $foo delegate { doX, doY };"
- Delegating static method calls to another class could also be supported, using a standalone declaration like "static delegate ClassName { staticMethodName };"
- As with Traits, the generated methods would be stitched into the class at compile time, and not distinguishable in reflection.
- Delegated methods could be used to implement an interface, either completely or partially (again, like Traits).
- Other features of traits could be included if they were seen as useful, such as aliasing ("delegate { foo as bar }") and changing visibility ("delegate { foo as private }")
Example:
class SpecialSessionHandlerDecorator implements \SessionHandlerInterface, SpecialInterface {
private \SessionHandlerInterface $delegatedHandler delegate {
close, destroy, gc, open, read, write
};
public function specialMethod() { ... }
}
What do people think? Would this be useful, or am I missing some major limitation or implementation problem? Does any other language provide a feature like this which we can learn from?
Regards,
--
Rowan Collins
[IMSoP]