Different Styles Of Delegation

Delegation (in OO) is the act of one object (the original object) forwarding a request (method call) from itself to another object (the delegate). Some claim that inheritance is a special case of (can be modeled by) delegation; however there are different styles of delegation.

See also WhatIsDelegation for a discussion of definitions. If more precise terminology is available, feel free to ReFactor this page.

Non-polymorphic delegation
(As seen in the BridgePattern). The delegate is not a supertype of the original object; once the forwarding call is made the original object has no affect on the operation of the delegate's method. In particular, if the delegate function calls another method on the delegate which is also defined in the original object, the delegate's version and not the original object's version is used.

Calling this non-polymorphic is somewhat dubious. Avoiding inheritance does not make you free of polymorphic behavior. Polymorphism does not depend on inheritance (see ConfusionAboutInheritance). The Bridge pattern has delegation, and a layer of indirection, therefore it's polymorphic (according to WhatIsDelegation; see also PolyMorphism).

Supertype delegation
Delegate is a supertype of the original object. In the case of real inheritance, the two objects are indistinguishable, supertype delegation is used to simulate this. What is desired if delegation is to model inheritance? If the delegate function calls another method on the delegate which is overridden in the original object, the original object's version is called. Note that is is often desirable in this case that the delegate be "hidden", and only accessible through the original object. (Again, this models inheritance; most OO languages will not let you override the typing system and invoke base-class methods directly from outside the object. It is discouraged in those that do allow this, such as CeePlusPlus).

Hybrid delegation
Delegate is not a supertype of the original object; however delegated method calls contain an additional pointer to the original object, which the implementation of the delegate may use to call original object methods.

An example from PrototypeBasedProgramming that might help:

What happens in a prototype language in the following case: object A delegates to object B; object A calls a method f on itself, which gets delegated to B; then B calls a method g on itself. If A also has a version of g, does that version get called (like in a traditional class-based language)? If so, that means that there always is an implicit "real" object beneath the curtain? -- StephanHouben

In the one prototype object language I've used in anger commercially, called Vision, the normal case is indeed that A's version of g is called, using
 ^self g
in the definition of f in the super-object (forget the ^ and it could be Smalltalk). Whereas
 ^here g
 ^current g
both explicitly call g as defined in B, the super-object. But whereas ^here keeps the original sub-object A in view for future method calls, ^current causes A to be forgotten and the computation to proceed simply as a message send to B. Easy isn't it?

Despite this necessary complication, the idioms of prototype-based programming have a lot going for them. Even JavaScript may help bringing some of this into the mainstream perhaps.

-- RichardDrake

View edit of August 15, 2010 or FindPage with title or text search