Delegates: Difference between revisions

From Rosetta Code
Content added Content deleted
(Typos)
No edit summary
Line 79: Line 79:
return 0;
return 0;
}
}
</pre>
==[[Pop11]]==
[[Category:Pop11]]

<pre>
uses objectclass;
define :class Delegator;
slot delegate = false;
enddefine;

define :class Delegate;
enddefine;

define :method thing(x : Delegate);
'delegate implementation'
enddefine;

define :method operation(x : Delegator);
if delegate(x) and fail_safe(delegate(x), thing) then
;;; Return value is on the stack
else
'default implementation'
endif;
enddefine;

;;; Default, without a delegate
lvars a = newDelegator();
operation(a) =>

;;; a delegating to itself (works because Delegator does not
;;; implement thing)
a -> delegate(a);
operation(a) =>

;;; delegating to a freshly created Delegate
newDelegate() -> delegate(a);
operation(a) =>

</pre>
</pre>



Revision as of 19:34, 20 October 2007

Task
Delegates
You are encouraged to solve this task according to the task description, using any language you may know.

A delegate is a helper object used by another object. The delegator may send the delegate certain messages, and provide a default implementation when there is no delegate or the delegate does not respond to a message. This pattern is heavily used in Cocoa framework on Mac OS X

Objects responsibilities:

Delegator:

  • Keep an optional delegate instance.
  • Implement "operation" method, returning the delegate "thing" if the delegate respond to "thing", or the string "default implementation".

Delegate:

  • Implement "thing" and return the string "delegate implementaion"

Show how objets are created and used. First, without a delegate, then with a delegate that does not implement "thing", and last with a delegate that implements "thing".

Objective-C

@interface Delegator : NSObject
{
    id delegate;
}
- (id)delegate;
- (void)setDelegate:(id)obj;
- (NSString *)operation;
@end

@implementation Delegator
- (id)delegate;
{
    return delegate;
}
- (void)setDelegate:(id)obj;
{
    delegate = obj; // Weak reference
}
- (NSString *)operation;
{
    if ([delegate respondsToSelector:@selector(thing)])
        return [delegate thing];
    return @"default implementation";
}
@end

// Any object may implement these
@interface NSObject (DelegatorDelegating)
- (NSString *)thing;
@end

@interface Delegate : NSObject
// Don't need to declare -thing because any NSObject has this method
@end

@implementation Delegate
- (NSString *)thing;
{
    return @"delegate implementation";
}
@end

// Example usage
// Memory management ignored for simplification
int main()
{
    // Without a delegate:
    Delegator *a = [[Delegator alloc] init];
    assert([[a operation] isEqualToString:@"default implementation"]);

    // With a delegate that does not implement thing:
    [a setDelegate:@"A delegate may be any object"];
    assert([isEqualToString:@"delegate implementation"]);

    // With a delegate that implements "thing":
    Delegate *d = [[Delegate alloc] init];
    [a setDelegate:d];
    assert([isEqualToString:@"delegate implementation"]);

    return 0;
}

Pop11

uses objectclass;
define :class Delegator;
    slot delegate = false;
enddefine;

define :class Delegate;
enddefine;

define :method thing(x : Delegate);
   'delegate implementation'
enddefine;

define :method operation(x : Delegator);
if delegate(x) and fail_safe(delegate(x), thing) then
   ;;; Return value is on the stack
else
   'default implementation'
endif;
enddefine;

;;; Default, without a delegate
lvars a = newDelegator();
operation(a) =>

;;; a delegating to itself (works because Delegator does not
;;; implement thing)
a -> delegate(a);
operation(a) =>

;;; delegating to a freshly created Delegate
newDelegate() -> delegate(a);
operation(a) =>

Python

class Delegator:
    def __init__(self):
        self.delegate = None
    def operation(self):
         if hasattr(self.delegate, 'thing'):
             return self.delegate.thing()
         return 'default implementation'

class Delegate:
    def thing(self):
        return 'delegate implementation'

if __name__ == '__main__':

    # No delegate
    a = Delegator()
    assert a.operation() == 'default implementation'

    # With a delegate that does not implement "thing"
    a.delegate = 'A delegate may be any object'
    assert a.operation() == 'default implementation'

    # With delegate that implements "thing"
    a.delegate = Delegate()
    assert a.operation() == 'delegate implementation'