Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:62153 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 38149 invoked from network); 14 Aug 2012 18:36:03 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 Aug 2012 18:36:03 -0000 Authentication-Results: pb1.pair.com smtp.mail=ircmaxell@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=ircmaxell@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 74.125.82.54 as permitted sender) X-PHP-List-Original-Sender: ircmaxell@gmail.com X-Host-Fingerprint: 74.125.82.54 mail-wg0-f54.google.com Received: from [74.125.82.54] ([74.125.82.54:48718] helo=mail-wg0-f54.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 0D/70-00812-29A9A205 for ; Tue, 14 Aug 2012 14:36:03 -0400 Received: by wgx1 with SMTP id 1so534119wgx.11 for ; Tue, 14 Aug 2012 11:35:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=/9yR5r+BjyX95LexaAzHpQ0BDUHiQRGU9zn7bqzGaB0=; b=s51nMnDOESdE6vBNOQzbPfu7slnq17fgYc7E1SaX8okfjhcBhqZbJZz4nzvqWWJDir 2M3U3YqNSepLormYDUU4a0yN6G44jb+jdwyi1ErTl655t82TuOzRMF4tBhyZf1pD8hRu b1YVuEKjKMhIw9SNrgxLrFsrEkzo4JO1v/O+3gFH6vjXtQVyGEj9bUEfzrEA3QTupFPB pqKIpWgVnk4nLyzUANVvfB2+BQJ4u02bHL3OkdbN/nSmrxu+fMuUNSkfRTqwfRec9G9g QOfbtoxi+m06poT8NBo/1DjaWV+duPPyOcyTk3QbWGVtcEGp8ZC7XlSXBb3R6HhAGsDg Eo0g== MIME-Version: 1.0 Received: by 10.216.226.36 with SMTP id a36mr8105481weq.58.1344969359572; Tue, 14 Aug 2012 11:35:59 -0700 (PDT) Received: by 10.180.103.195 with HTTP; Tue, 14 Aug 2012 11:35:59 -0700 (PDT) In-Reply-To: <502A81AD.1070303@ralphschindler.com> References: <502A81AD.1070303@ralphschindler.com> Date: Tue, 14 Aug 2012 14:35:59 -0400 Message-ID: To: Ralph Schindler Cc: internals@lists.php.net Content-Type: multipart/alternative; boundary=0016e6dd96a5e93ebe04c73e1488 Subject: Re: [PHP-DEV] Decorators Revisited From: ircmaxell@gmail.com (Anthony Ferrara) --0016e6dd96a5e93ebe04c73e1488 Content-Type: text/plain; charset=ISO-8859-1 Ralph, On Tue, Aug 14, 2012 at 12:49 PM, Ralph Schindler wrote: > In general, I think it would be nice to have something that does this for > you, but I am not necessarily a fan of changing the meaning of instanceof. > > > That's a lot of boilerplate for each possible iteration. This is one >> reason >> people like traits so much, as it's easier to just do automated copy/paste >> than use the proper patterns. >> > > Couldn't a dynamic trait be a better? It would work like this: > > trait SplDynamicProxyTrait { > > protected $proxyObject; > > // enumerate all public method with the following: > public function $name($signature) { > return $this->proxyObject::$name($**signature); > } > > } > > usage would then be the following: > > class MyDecorator implements FooInterface { > use SplDynamicProxyTrait; // compile time "code generation" > public function __construct(Foo $foo) { > $this->proxyObject = $foo; > } > // override trait > > public function method2($a) { > if (!$this->hasCache('method2', $a)) { > $ret = $this->proxyObject->method2($**a); > > $this->setCache('method2', $a, $ret); > } > return $this->getCache('method2', $a); > } > } > > > So, example code like: >> >> class Foo {} >> class Bar extends SplDecorator {} >> $b = new Bar(new Foo); >> var_dump($b instanceof Foo); // true >> >> It also works with type hints: >> function test(Foo $f) {} >> test($b); >> > > These would all still work, instanceof would actually be an instanceof > though. > > > Now, there's a lot more to do (property cascading, interface validation, >> etc), but the initial proof-of-concept is there. >> > > What do you think? Is this a route that I should continue down? Or is >> there >> something fundamental that I'm missing here? I know that Reflection, >> get_interfaces(), etc would need to be updated to account for this. >> >> Thoughts? >> > > In the above scenario, we've reused traits and we haven't broken > instanceof or the liskov principle (which basically your implementation > does since SplDectorator bypasses all method signature checking until > runtime). > > Thoughts? :) > > -ralph Well, I like it at first glance. There are two main problems that I see with it: 1. It still requires a separate decorator class for every combination of interfaces you want to decorate. So, for example if you wanted to decorate a Foo interface, but sometimes it's used with Iterator as well. Then you'd need two classes. If there was a third interface, you'd need four separate classes. Same problem with class bloat minus a lot of the boilerplate. 2. It's still not possible to decorate a typed class. So I can't decorate PDO without first extending PDO with a user-supplied interface. And I don't understand how this breaks LSP... We're not extending the decorated class. In fact, we can add construct time checking to ensure the original interfaces are all enforced (and even go a step further and ensure that all method signatures are the same that are overridden). LSP is not a compile time concern, it's a purely runtime concern (in PHP at least). The fact that interface contracts are enforced at compile time is nice, but it's not a strict necessity to enforcing LSP. Anthony --0016e6dd96a5e93ebe04c73e1488--