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