Ralph,

to write. This is one of the reasons that traits are so heralded.
>> Because problems that are easy to solve with decorators (in general) are
>> difficult to solve with PHP, so people wind up writing copy/paste
>>
>
> If what you're trying to do is decorate an instance of a particular
> concrete type, the basic structure/foundation for creating a Decorator (as
> defined by wikipedia), can be achieved in PHP with about 3 lines of code:
>
> class FooDecorator extends Foo {
>     protected $subject;
>     public function __construct(Foo $foo) {
>         $this->subject = $foo;
>         foreach (get_object_vars($foo) as $n => $v) {
>             $this->{$n} =& $foo->{$n};
>         }
>     }
> }
>
> At this point, any instance of new Foo is statefully and type equivalent
> to new FooDecorator($foo).  Now, you're free to add in your custom
> decoration logic, overridden methods, additional methods, new interfaces,
> etc.  An instance of FooDecorator can be used an any place an instance of
> Foo would have been used.  i.e., it's bound to the Foo context.


That's an alternative? Really? Some hackery involving inheritance abuse...?

Let me pose a real world example.

Let's say you have a house. Let's call it `class House`. Then let's say you
want to add christmas lights to it. You don't go bulldoze the existing
house and construct a new one (class HouseWithLights). And you don't create
a new one, move all the furnature into the new one and then move the
original one to another temporary spot (your "extends" example). You go get
lights (class Lights) and decorate the existing house with them. All the
properties and features of the house still exist, but with the added
functionality (and responsibility) of the new lights.

Then, let's say you want to add a deck. You don't create a new class
HouseWithLightsAndDeck. You add the deck to the existing instance.

Now, you could also do this with a bridge pattern. But with a bridge, you
need to specially design the construction for the particular type you're
doing. So you would build a bridge for a house, and a separate one for an
office building. But with a decorator, you could decorate both the house
and the office building with the same lights, and the same deck.

And I don't need to resort to duck typing for it to work. All I need is
>> the ability to decorate at will. I'm not talking about nuking the
>> meaning of the interfaces (as they'd be proxied to). But more just
>>
>
> We're going to have to disagree on the "meaning of interfaces". Interfaces
> are a foundational element of a class based type hierarchy. If you want
> Interfaces without them being in an instance type hierarchy, I'm not sure
> what you call that; but it's not an Interface. The decisions made in the
> PHP group around the class type system more closely resemble those made by
> Java and C#.
>

I'm absolutely talking about the interfaces being in the *instance* type
hiearchy. That's the whole point of the proposal. What I'm talking about
here is adding the ability for it to be in the instance type hiearchy
without it being in the class hiearchy...


> Concerning your code snippets above.
>
> It sounds like you want to dynamically build classes and methods, on the
> fly, or you want a magical subclass that is free from the current rules of
> is_a, instanceof, etc.
>

Absolutely not. What I'm talking about is a "magic class" which *inherits*
type information from its parent. Not which will magically pass all
instanceof queries. It would behave as if you extended whatever class was
passed in, without doing the actual extension (and all the coupling baggage
that comes with)...


> Put another way, some developer somewhere built a system and has a method
> signature like
>
> class Controller {
>    public function dispatch(Dispatchable $dispatchable) { ... }
> }
>
> and they have provided the Dispatchable interface.  But you want to take
> any old object that does not implement Dispatchable and be able to modify
> it on the fly to bypass his type check in his type check in the method
> signature of his dispatch().


Not in the least. I want to be able to take an existing object that
implements Dispatchable, and wrap that with my decorator to either add new
functionality or alter existing (while keeping the typing contracts
enforced, so the interface of the parent cannot be violated in the
decorator without a construction time error).


>  to solve this problem. I'm talking about runtime composability of
>> functionality. Not compile time. I want to be able to construct my
>> objects from other interactions (like database settings), not just be
>> limited to having to copy/paste for everything.
>>
>
> That's just crazy talk right there! ;)
>
> composing functionality != composing types
>
> In PHP (currently, as anything could change), is_a, instanceof and method
> type signatures are used by people who believe in a class based type
> inheritance system and the system of checks built around that.
>

And I'm not arguing that in the least. In fact, I'm embracing that by
allowing a whole lot of boilerplate code to be saved. Not just the
individual proxy methods that the decorator would use, but also the
multiple versions of the decorator for every possible type combination that
it could decorate.


> Your proposal attempts to change that such that special types can be
> exempt from the type checking rules for the purpose of a particular pattern
> (Decorator).  I've personally never had a problems with decorating, so it
> is hard for me to envision the system you are building where Decorators are
> a problem.


Again, not at all. The type tree would still need to be there at runtime.
$foo instanceof Foo would still mean that either $foo is a Foo object, or
it's a decorated Foo object. But there's still a Foo object in the chain.
The chain is just dynamically assembled at runtime. That's the whole point
of this...

Think of this similar in concept to mixins. They are allowed to be added
dynamically at runtime to alter behavior without all the baggage that
traditional inheritance brings to the table...

Anthony

Reply via email to