Ralph,

On Tue, Aug 14, 2012 at 12:49 PM, Ralph Schindler
<ra...@ralphschindler.com>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

Reply via email to