Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:103353 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 40431 invoked from network); 21 Oct 2018 21:26:43 -0000 Received: from unknown (HELO mail-wm1-f42.google.com) (209.85.128.42) by pb1.pair.com with SMTP; 21 Oct 2018 21:26:43 -0000 Received: by mail-wm1-f42.google.com with SMTP id z25-v6so7555543wmf.1 for ; Sun, 21 Oct 2018 10:41:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=to:from:subject:message-id:date:user-agent:mime-version :content-transfer-encoding:content-language; bh=u6Riairq/TKgY/HqjKyWVX3wLqmrHXRZ0MZR75U53sM=; b=A4v/aFVt2l89l6fFfxP06CwrUcZl+5ycJQQn02F01Po77MrrtnYiaeI484Pa9lWxxB 3tFHYSNhsneznJY507HKzs0aKhq42eYR3mg7YpVbEHk6kS7NOADzCyOHOcRD0I5x6pD2 5QVsj/4X5/DGPI8sXfRIS6RLWPldCk3Rh04U/rDyOxfX9pfPyFI7JrSIkx0PMY8/mCWW rxJYWZ4ce0u6WHtYeQL5UYyQuKWxFA4LKviwKyD+vmw1B0A42Wsusa9boAJGWgQ6GYaD Oyqi4sh3bVGMNAGFDko/uRXaFXWeyyST6HRnqDUkxQPH6vjurO0fspF0N3V56UKdbrs5 OlLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding:content-language; bh=u6Riairq/TKgY/HqjKyWVX3wLqmrHXRZ0MZR75U53sM=; b=lGdzrs6zNUQqs0fvUln6DZLt16O6yDRlvqq7bY0cxMk9X/6TWjEALY/7GTDDcxKgzq oLgvn636duSYFNR2IRQKtOyUCNnVjPNLCjkF56RC+nkgH1r4ZL8ahLkevh32JGRp5lXG 85nPrrt/Z7zt8mjOPXHGtnq69Gf1OhxJP7ok5O3bpBhAbx6l0NCz59PCLFeua8CccPwX AMYyErYb4rx308tQqzvGZZArxqCAxqe1QNYX3ds8n+blu+3hZ/BbjRGMcQ/JXxLW4AhK tFmY/McCCs94ySpkZpAbjHfyqQAy9bO6Y8h5Jro7fleMA1s0R3peJfM5qd71u+fBpz2t V3xQ== X-Gm-Message-State: ABuFfojPF+RY4fUJT1axGo3vEN174q2WJVq9jwiKpGtlFrm8q4/oPAIk gXX3UPFrS6K9NJ62YLnH+ysozS77 X-Google-Smtp-Source: ACcGV60Qr0SDMhN1paDRISpWg2GKwKforBznfwXa5KYgMobMngODzvH+FfbJBGIot70SyGvxl0fKOA== X-Received: by 2002:a1c:af07:: with SMTP id y7-v6mr13091512wme.12.1540143667515; Sun, 21 Oct 2018 10:41:07 -0700 (PDT) Received: from [192.168.0.14] (cpc84253-brig22-2-0-cust114.3-3.cable.virginm.net. [81.108.141.115]) by smtp.googlemail.com with ESMTPSA id m12sm25343968wrx.75.2018.10.21.10.41.06 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 21 Oct 2018 10:41:06 -0700 (PDT) To: PHP Internals Message-ID: <0047f3c7-3e9e-ef6f-2d7a-e58c316ea751@gmail.com> Date: Sun, 21 Oct 2018 18:41:04 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.2.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-GB Subject: Composition over inheritance: native support for "delegating" methods? From: rowan.collins@gmail.com (Rowan Collins) 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]