Forwarding (object-oriented programming)
In object-oriented programming, forwarding means that using a member of an object (either a property or a method) results in actually using the corresponding member of a different object: the use is forwarded to another object. Forwarding is used in a number of design patterns, where some members are forwarded to another object, while others are handled by the directly used object. The forwarding object is frequently called a wrapper object, and explicit forwarding members are called wrapper functions.
Forwarding is a simple form of delegation, and is distinguished from more general delegation in that in forwarding, the original object is not used by the delegate, and the delegation is a direct pass-through. Forwarding fulfills a similar purpose to inheritance, in allowing behavioral reuse (and concretely code reuse), but differs in having two separate objects, rather than a single object. In fact, in prototype-based programming, inheritance is typically implemented by delegation (retaining the original object); while in class-based programming forwarding allows reuse to be determined at run time (based on the object to which use is forwarded), rather than at compile time (based on the class which is inherited from). Forwarding is thus considerably more flexible than inheritance, but potentially more complex as well.
Examples
A simple example of explicit forwarding in Java: an instance of B
forwards calls to the foo
method to its a
field:
class B {
A a;
T foo() { return a.foo(); }
}
Note that when executing a.foo()
, the this
object is a
(a subtype of A
), not the original object (an instance of B
). Further, a
need not be an instance of A
: it may be an instance of a subtype. Indeed, A
need not even be a class: it may be an interface/protocol.
Contrast with inheritance, in which foo
is defined in a superclass A
(which must be a class, not an interface), and when called on an instance of a subclass B
, it uses the code defined in A
, but the this
object is still an instance of B
:
class A {
T foo() { /* ... */ };
}
class B extends A {
}
In this Python example, class B
forwards the foo
method and the x
property to the object in its a
field: using these on b
(an instance of B
) is the same as using them on b.a
(the instance of A
to which these are forwarded).
class A:
def __init__(self, x):
self.x = x
def foo(self):
print(self.x)
class B:
def __init__(self, a):
self.a = a
def foo(self):
a.foo()
@property
def x(self):
return a.x
@x.setter
def x(self, x):
a.x = x
@x.deleter
def x(self):
del a.x
a = A(42)
b = B(a)
b.foo() # Prints '42'.
b.x # Has value '42'
b.x = 17 # b.a.x now has value 17
del b.x # Deletes b.a.x.
Applications
Forwarding is used in many design patterns.[1] Forwarding is used directly in several patterns:
- Chain-of-responsibility pattern
- Decorator pattern: decorator object adds its own members, forwarding others to the decorated object.
- Proxy pattern: proxy object forwards member use to real object.
Forwarding may be used in other patterns, but often use is modified; for example, a method call on one object results in several different methods being called on another: