Delegates

From Rosetta Code
(Redirected from Delegate)
Jump to: navigation, search
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. See also wp:Delegation pattern.

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 implementation"

Show how objects 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".

Contents

[edit] Ada

All that is needed in order to implement this is a common base type. The delegator holds a pointer to an "untyped" object from the base class. Querying if the target implements the delegate interface is done using run-time type identification.

with Ada.Text_IO;  use Ada.Text_IO;
 
procedure Delegation is
package Things is
-- We need a common root for our stuff
type Object is tagged null record;
type Object_Ptr is access all Object'Class;
 
-- Objects that have operation thing
type Substantial is new Object with null record;
function Thing (X : Substantial) return String;
 
-- Delegator objects
type Delegator is new Object with record
Delegate : Object_Ptr;
end record;
function Operation (X : Delegator) return String;
 
No_Thing  : aliased Object; -- Does not have thing
Has_Thing : aliased Substantial; -- Has one
end Things;
 
package body Things is
function Thing (X : Substantial) return String is
begin
return "delegate implementation";
end Thing;
 
function Operation (X : Delegator) return String is
begin
if X.Delegate /= null and then X.Delegate.all in Substantial'Class then
return Thing (Substantial'Class (X.Delegate.all));
else
return "default implementation";
end if;
end Operation;
end Things;
 
use Things;
 
A : Delegator; -- Without a delegate
begin
Put_Line (A.Operation);
A.Delegate := No_Thing'Access; -- Set no thing
Put_Line (A.Operation);
A.Delegate := Has_Thing'Access; -- Set a thing
Put_Line (A.Operation);
end Delegation;

Sample output:

default implementation
default implementation
delegate implementation

[edit] Aime

text
thing(void)
{
return "delegate implementation";
}
 
text
operation(record delegator)
{
text s;
 
if (r_key(delegator, "delegate")) {
if (r_key(r_query(delegator, "delegate"), "thing")) {
s = __text(call(r_query(r_query(delegator, "delegate"), "thing")));
} else {
s = "default implementation";
}
} else {
s = "default implementation";
}
 
return s;
}
 
integer
main(void)
{
record delegate, delegator;
 
o_text(operation(delegator));
o_byte('\n');
 
r_link(delegator, "delegate", delegate);
o_text(operation(delegator));
o_byte('\n');
 
r_put(delegate, "thing", thing);
o_text(operation(delegator));
o_byte('\n');
 
return 0;
}

[edit] Aikido

 
class Delegator {
public generic delegate = none
 
public function operation {
if (typeof(delegate) == "none") {
return "default implementation"
}
return delegate()
}
}
 
function thing {
return "delegate implementation"
}
 
// default, no delegate
var d = new Delegator()
println (d.operation())
 
// delegate
var d1 = new Delegator()
d1.delegate = thing
println (d1.operation())
 
 

[edit] C

As best you can do, without support for classes.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef const char * (*Responder)( int p1);
 
typedef struct sDelegate {
Responder operation;
} *Delegate;
 
/* Delegate class constructor */
Delegate NewDelegate( Responder rspndr )
{
Delegate dl = malloc(sizeof(struct sDelegate));
dl->operation = rspndr;
return dl;
}
 
/* Thing method of Delegate */
const char *DelegateThing(Delegate dl, int p1)
{
return (dl->operation)? (*dl->operation)(p1) : NULL;
}
 
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
typedef struct sDelegator {
int param;
char *phrase;
Delegate delegate;
} *Delegator;
 
const char * defaultResponse( int p1)
{
return "default implementation";
}
 
static struct sDelegate defaultDel = { &defaultResponse };
 
/* Delegator class constructor */
Delegator NewDelegator( int p, char *phrase)
{
Delegator d = malloc(sizeof(struct sDelegator));
d->param = p;
d->phrase = phrase;
d->delegate = &defaultDel; /* default delegate */
return d;
}
 
/* Operation method of Delegator */
const char *Delegator_Operation( Delegator theDelegator, int p1, Delegate delroy)
{
const char *rtn;
if (delroy) {
rtn = DelegateThing(delroy, p1);
if (!rtn) { /* delegate didn't handle 'thing' */
rtn = DelegateThing(theDelegator->delegate, p1);
}
}
else /* no delegate */
rtn = DelegateThing(theDelegator->delegate, p1);
 
printf("%s\n", theDelegator->phrase );
return rtn;
}
 
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
const char *thing1( int p1)
{
printf("We're in thing1 with value %d\n" , p1);
return "delegate implementation";
}
 
int main()
{
Delegate del1 = NewDelegate(&thing1);
Delegate del2 = NewDelegate(NULL);
Delegator theDelegator = NewDelegator( 14, "A stellar vista, Baby.");
 
printf("Delegator returns %s\n\n",
Delegator_Operation( theDelegator, 3, NULL));
printf("Delegator returns %s\n\n",
Delegator_Operation( theDelegator, 3, del1));
printf("Delegator returns %s\n\n",
Delegator_Operation( theDelegator, 3, del2));
return 0;
}

[edit] C#

using System;
 
interface IOperable
{
string Operate();
}
 
class Inoperable
{
}
 
class Operable : IOperable
{
public string Operate()
{
return "Delegate implementation.";
}
}
 
class Delegator : IOperable
{
object Delegate;
 
public string Operate()
{
var operable = Delegate as IOperable;
return operable != null ? operable.Operate() : "Default implementation.";
}
 
static void Main()
{
var delegator = new Delegator();
foreach (var @delegate in new object[] { null, new Inoperable(), new Operable() })
{
delegator.Delegate = @delegate;
Console.WriteLine(delegator.Operate());
}
}
}

Output:

Default implementation.
Default implementation.
Delegate implementation.

[edit] C++

Delegates in the C# or D style are available in C++ through std::tr1::function class template. These delegates don't exactly match this problem statement though, as they only support a single method call (which is operator()), and so don't support querying for support of particular methods.

 
#include <tr1/memory>
#include <string>
#include <iostream>
#include <tr1/functional>
 
using namespace std;
using namespace std::tr1;
using std::tr1::function;
 
// interface for all delegates
class IDelegate
{
public:
virtual ~IDelegate() {}
};
 
//interface for delegates supporting thing
class IThing
{
public:
virtual ~IThing() {}
virtual std::string Thing() = 0;
};
 
// Does not handle Thing
class DelegateA : virtual public IDelegate
{
};
 
// Handles Thing
class DelegateB : public IThing, public IDelegate
{
std::string Thing()
{
return "delegate implementation";
}
};
 
class Delegator
{
public:
std::string Operation()
{
if(Delegate) //have delegate
if (IThing * pThing = dynamic_cast<IThing*>(Delegate.get()))
//delegate provides IThing interface
return pThing->Thing();
 
return "default implementation";
}
 
shared_ptr<IDelegate> Delegate;
};
 
int main()
{
shared_ptr<DelegateA> delegateA(new DelegateA());
shared_ptr<DelegateB> delegateB(new DelegateB());
Delegator delegator;
 
// No delegate
std::cout << delegator.Operation() << std::endl;
 
// Delegate doesn't handle "Thing"
delegator.Delegate = delegateA;
std::cout << delegator.Operation() << std::endl;
 
// Delegate handles "Thing"
delegator.Delegate = delegateB;
std::cout << delegator.Operation() << std::endl;
 
/*
Prints:
 
default implementation
default implementation
delegate implementation
*/

}
 

[edit] CoffeeScript

Translation of: Python
 
class Delegator
operation: ->
if @delegate and typeof (@delegate.thing) is "function"
return @delegate.thing()
"default implementation"
 
class Delegate
thing: ->
"Delegate Implementation"
 
testDelegator = ->
# Delegator with no delegate.
a = new Delegator()
console.log a.operation()
 
# Delegator with delegate not implementing "thing"
a.delegate = "A delegate may be any object"
console.log a.operation()
 
# Delegator with delegate that does implement "thing"
a.delegate = new Delegate()
console.log a.operation()
 
testDelegator()
 

output

 
> coffee foo.coffee
default implementation
default implementation
Delegate Implementation
 

[edit] Common Lisp

Translation of: Python

In CLOS, methods exist apart from classes, and are specialized based on the types of their arguments. This example defines two classes (delegator and delegate), and a thing generic method which is specialized in three ways: (1) for 'any' argument, providing a default method; (2) for delegators, where thing is recursively applied to the delegator's delegate (if there is one); and (3) for delegates.

(defgeneric thing (object)
(:documentation "Thing the object."))
 
(defmethod thing (object)
"default implementation")
 
(defclass delegator ()
((delegate
:initarg :delegate
:reader delegator-delegate)))
 
(defmethod thing ((delegator delegator))
"If delegator has a delegate, invoke thing on the delegate,
otherwise return \"no delegate\"."

(if (slot-boundp delegator 'delegate)
(thing (delegator-delegate delegator))
"no delegate"))
 
(defclass delegate () ())
 
(defmethod thing ((delegate delegate))
"delegate implementation")
 
(let ((d1 (make-instance 'delegator))
(d2 (make-instance 'delegator :delegate nil))
(d3 (make-instance 'delegator :delegate (make-instance 'delegate))))
(assert (string= "no delegate" (thing d1)))
(assert (string= "default implementation" (thing d2)))
(assert (string= "delegate implementation" (thing d3))))

[edit] D

D has built-in delegates, so we can skip creating an additional Delegate object and pass a real delegate directly to Delegator.

class Delegator {
string delegate() hasDelegate;
 
string operation() {
if (hasDelegate is null)
return "Default implementation";
return hasDelegate();
}
 
typeof(this) setDg(string delegate() dg) {
hasDelegate = dg;
return this;
}
}
 
void main() {
import std.stdio;
auto dr = new Delegator;
string delegate() thing = () => "Delegate implementation";
 
writeln(dr.operation());
writeln(dr.operation());
writeln(dr.setDg(thing).operation());
}
Output:
Default implementation
Default implementation
Delegate implementation

[edit] Version using Tango

Library: tango
import tango.io.Stdout;
 
class Delegator
{
private char[] delegate() hasDelegate;
public:
char[] operation() {
if (hasDelegate is null)
return "default implementation";
return hasDelegate();
}
 
typeof(this) setDg(char[] delegate() dg)
{
hasDelegate = dg;
return this;
}
}
 
int main(char[][] args)
{
auto dr = new Delegator();
auto thing = delegate char[]() { return "delegate implementation"; };
 
Stdout ( dr.operation ).newline;
Stdout ( dr.operation ).newline;
Stdout ( dr.setDg(thing).operation ).newline;
return 0;
}

[edit] Dart

I didn't find a way to check for existing methods, so the version with Object doesn't work yet. The code is adapted from the Java version, but using var instead of an Interface

class Delegator {
var delegate;
 
String operation() {
if (delegate == null)
return "default implementation";
else
return delegate.thing();
}
}
 
class Delegate {
String thing() => "delegate implementation";
}
 
main() {
// Without a delegate:
Delegator a = new Delegator();
Expect.equals("default implementation",a.operation());
 
// any object doesn't work unless we can check for existing methods
// a.delegate=new Object();
// Expect.equals("default implementation",a.operation());
 
// With a delegate:
Delegate d = new Delegate();
a.delegate = d;
Expect.equals("delegate implementation",a.operation());
}

[edit] Delphi

Translation of the Java example found at Wikipedia.

unit Printer;
 
interface
 
type
// the "delegate"
TRealPrinter = class
public
procedure Print;
end;
 
// the "delegator"
TPrinter = class
private
FPrinter: TRealPrinter;
public
constructor Create;
destructor Destroy; override;
procedure Print;
end;
 
implementation
 
{ TRealPrinter }
 
procedure TRealPrinter.Print;
begin
Writeln('Something...');
end;
 
{ TPrinter }
 
constructor TPrinter.Create;
begin
inherited Create;
FPrinter:= TRealPrinter.Create;
end;
 
destructor TPrinter.Destroy;
begin
FPrinter.Free;
inherited;
end;
 
procedure TPrinter.Print;
begin
FPrinter.Print;
end;
 
end.
program Delegate;
 
{$APPTYPE CONSOLE}
 
uses
SysUtils,
Printer in 'Printer.pas';
 
var
PrinterObj: TPrinter;
begin
PrinterObj:= TPrinter.Create;
try
PrinterObj.Print;
Readln;
finally
PrinterObj.Free;
end;
end.

[edit] E

def makeDelegator {
/** construct without an explicit delegate */
to run() {
return makeDelegator(null)
}
 
/** construct with a delegate */
to run(delegateO) { # suffix because "delegate" is a reserved keyword
def delegator {
to operation() {
return if (delegateO.__respondsTo("thing", 0)) {
delegateO.thing()
} else {
"default implementation"
}
}
}
return delegator
}
}
 
? def delegator := makeDelegator()
> delegator.operation()
# value: "default implementation"
 
? def delegator := makeDelegator(def doesNotImplement {})
> delegator.operation()
# value: "default implementation"
 
? def delegator := makeDelegator(def doesImplement {
> to thing() { return "delegate implementation" }
> })
> delegator.operation()
# value: "default implementation"

[edit] F#

type Delegator() =
let defaultOperation() = "default implementation"
let mutable del = null
 
// write-only property "Delegate"
member x.Delegate with set(d:obj) = del <- d
 
member x.operation() =
if del = null then
defaultOperation()
else
match del.GetType().GetMethod("thing", [||]) with
| null -> defaultOperation()
| thing -> thing.Invoke(del, [||]) :?> string
 
type Delegate() =
member x.thing() = "delegate implementation"
 
let d = new Delegator()
assert (d.operation() = "default implementation")
 
d.Delegate <- "A delegate may be any object"
assert (d.operation() = "default implementation")
 
d.Delegate <- new Delegate()
assert (d.operation() = "delegate implementation")

[edit] Go

package main
import "fmt"
 
type Delegator struct {
delegate interface{} // the delegate may be any type
}
 
// interface that represents anything that supports thing()
type Thingable interface {
thing() string
}
 
func (self Delegator) operation() string {
if v, ok := self.delegate.(Thingable); ok {
return v.thing()
}
return "default implementation"
}
 
type Delegate int // any dummy type
 
func (Delegate) thing() string {
return "delegate implementation"
}
 
func main() {
// Without a delegate:
a := Delegator{}
fmt.Println(a.operation()) // prints "default implementation"
 
// With a delegate that does not implement "thing"
a.delegate = "A delegate may be any object"
fmt.Println(a.operation()) // prints "default implementation"
 
// With a delegate:
var d Delegate
a.delegate = d
fmt.Println(a.operation()) // prints "delegate implementation"
}

[edit] J

Life becomes slightly cleaner if we delegate to ourselves in the absence of some other delegate.

coclass 'delegator'
operation=:3 :'thing__delegate ::thing y'
thing=: 'default implementation'"_
setDelegate=:3 :'delegate=:y' NB. result is the reference to our new delegate
delegate=:<'delegator'
 
coclass 'delegatee1'
 
coclass 'delegatee2'
thing=: 'delegate implementation'"_
 
NB. set context in case this script was used interactively, instead of being loaded
cocurrent 'base'

Example use:

   obj=:conew'delegator'
operation__obj''
default implementation
setDelegate__obj conew'delegatee1'
┌─┐
4
└─┘
operation__obj''
default implementation
setDelegate__obj conew'delegatee2'
┌─┐
5
└─┘
operation__obj''
delegate implementation

[edit] Java

This implementation uses an interface called Thingable to specify the type of delegates that respond to thing(). The downside is that any delegate you want to use has to explicitly declare to implement the interface. The upside is that the type system guarantees that when the delegate is non-null, it must implement the "thing" method.

interface Thingable {
String thing();
}
 
class Delegator {
public Thingable delegate;
 
public String operation() {
if (delegate == null)
return "default implementation";
else
return delegate.thing();
}
}
 
class Delegate implements Thingable {
public String thing() {
return "delegate implementation";
}
}
 
// Example usage
// Memory management ignored for simplification
public class DelegateExample {
public static void main(String[] args) {
// Without a delegate:
Delegator a = new Delegator();
assert a.operation().equals("default implementation");
 
// With a delegate:
Delegate d = new Delegate();
a.delegate = d;
assert a.operation().equals("delegate implementation");
 
// Same as the above, but with an anonymous class:
a.delegate = new Thingable() {
public String thing() {
return "anonymous delegate implementation";
}
};
assert a.operation().equals("anonymous delegate implementation");
}
}

[edit] JavaScript

Translation of: Python
function Delegator() {
this.delegate = null ;
this.operation = function(){
if(this.delegate && typeof(this.delegate.thing) == 'function')
return this.delegate.thing() ;
return 'default implementation' ;
}
}
 
function Delegate() {
this.thing = function(){
return 'Delegate Implementation' ;
}
}
 
function testDelegator(){
var a = new Delegator() ;
document.write(a.operation() + "\n") ;
 
a.delegate = 'A delegate may be any object' ;
document.write(a.operation() + "\n") ;
 
a.delegate = new Delegate() ;
document.write(a.operation() + "\n") ;
}

[edit] Logtalk

We use prototypes instead of classes for simplicity.

% define a category for holding the interface
% and implementation for delegator objects
 
:- category(delegator).
 
:- public(delegate/1).
:- public(set_delegate/1).
 
:- private(delegate_/1).
:- dynamic(delegate_/1).
 
delegate(Delegate) :-
::delegate_(Delegate).
 
set_delegate(Delegate) :-
::retractall(delegate_(Delegate)),
::assertz(delegate_(Delegate)).
 
:- end_category.
 
% define a simpler delegator object, with a
% method, operation/1, for testing delegation
 
:- object(a_delegator,
imports(delegator)).
 
:- public(operation/1).
 
operation(String) :-
( ::delegate(Delegate), Delegate::current_predicate(thing/1) ->
% a delegate is defined that understands the method thing/1
Delegate::thing(String)
; % otherwise just use the default implementation
String = 'default implementation'
).
 
:- end_object.
 
% define an interface for delegate objects
 
:- protocol(delegate).
 
:- public(thing/1).
 
:- end_protocol.
 
% define a simple delegate
 
:- object(a_delegate,
implements(delegate)).
 
thing('delegate implementation').
 
:- end_object.
 
% define a simple object that doesn't implement the "delegate" interface
 
:- object(an_object).
 
:- end_object.
 
% test the delegation solution when this file is compiled and loaded
 
:- initialization((
% without a delegate:
a_delegator::operation(String1),
String1 == 'default implementation',
% with a delegate that does not implement thing/1:
a_delegator::set_delegate(an_object),
a_delegator::operation(String2),
String2 == 'default implementation',
% with a delegate that implements thing/1:
a_delegator::set_delegate(a_delegate),
a_delegator::operation(String3),
String3 == 'delegate implementation'
)).

[edit] Objective-C

Classic Objective-C

Works with: Cocoa
Works with: GNUstep
#import <Foundation/Foundation.h>
 
@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];
NSLog(@"%d\n", [[a operation] isEqualToString:@"default implementation"]);
 
// With a delegate that does not implement thing:
[a setDelegate:@"A delegate may be any object"];
NSLog(@"%d\n", [[a operation] isEqualToString:@"delegate implementation"]);
 
// With a delegate that implements "thing":
Delegate *d = [[Delegate alloc] init];
[a setDelegate:d];
NSLog(@"%d\n", [[a operation] isEqualToString:@"delegate implementation"]);
 
return 0;
}

Objective-C 2.0, modern runtime, Automatic Reference Counting, Autosynthesize (LLVM 4.0+)

Works with: Cocoa
#import <Foundation/Foundation.h>
 
// Formal protocol for the delegate
@protocol DelegatorDelegatingProtocol
- (NSString *)thing;
@end
 
@interface Delegator : NSObject
@property (weak) id delegate;
- (NSString *)operation;
@end
@implementation Delegator
- (NSString *)operation {
if ([self.delegate respondsToSelector: @selector(thing)])
return [self.delegate thing];
 
return @"default implementation";
}
@end
 
@interface Delegate : NSObject
<DelegatorDelegatingProtocol>
@end
@implementation Delegate
- (NSString *)thing { return @"delegate implementation"; }
@end
 
// Example usage with Automatic Reference Counting
int main() {
@autoreleasepool {
// Without a delegate:
Delegator *a = [Delegator new];
NSLog(@"%@", [a operation]); // prints "default implementation"
 
// With a delegate that does not implement thing:
a.delegate = @"A delegate may be any object";
NSLog(@"%@", [a operation]); // prints "default implementation"
 
// With a delegate that implements "thing":
Delegate *d = [Delegate new];
a.delegate = d;
NSLog(@"%@", [a operation]); // prints "delegate implementation"
}
return 0;
}

[edit] ooRexx

 
delegator = .delegator~new -- no delegate
say delegator~operation
-- an invalid delegate type
delegator~delegate = "Some string"
say delegator~operation
-- a good delegate
delegator~delegate = .thing~new
say delegator~operation
-- a directory object with a thing entry defined
d = .directory~new
d~thing = "delegate implementation"
delegator~delegate = d
say delegator~operation
 
-- a class we can use as a delegate
::class thing
::method thing
return "delegate implementation"
 
::class delegator
::method init
expose delegate
use strict arg delegate = .nil
 
::attribute delegate
 
::method operation
expose delegate
if delegate == .nil then return "default implementation"
 
-- Note: We could use delegate~hasMethod("THING") to check
-- for a THING method, but this will fail of the object relies
-- on an UNKNOWN method to handle the method. By trapping
-- NOMETHOD conditions, we can allow those calls to go
-- through
signal on nomethod
return delegate~thing
 
nomethod:
return "default implementation"
 

[edit] OxygenBasic

 
class DelegateA 'not implmenting thing()
'==============
'
string message
 
end class
 
class DelegateB 'implementing thing()
'==============
'
string message
 
method thing() as string
return message
end method
'
end class
 
 
Class Delegator
'==============
'
has DelegateA dgA
has DelegateB dgB
'
method operation() as DelegateB
dgB.message="Delegate Implementation"
return @dgB
end method
 
method thing() as string
return "not using Delegate"
end method
'
end class
 
'====
'TEST
'====
 
Delegator dgr
let dg=dgr.operation
print dgr.thing 'result "not using Delegate"
print dg.thing 'result "Delegate Implementation"
 

[edit] Oz

Translation of: Python
declare
class Delegator from BaseObject
attr
delegate:unit
 
meth set(DG)
{Object.is DG} = true %% assert: DG must be an object
delegate := DG
end
 
meth operation($)
if @delegate == unit then
{self default($)}
else
try
{@delegate thing($)}
catch error(object(lookup ...) ...) then
%% the delegate did not understand the message
{self default($)}
end
end
end
 
meth default($)
"default implementation"
end
end
 
class Delegate from BaseObject
meth thing($)
"delegate Implementation"
end
end
 
A = {New Delegator noop}
in
{System.showInfo {A operation($)}}
 
{A set({New BaseObject noop})}
{System.showInfo {A operation($)}}
 
{A set({New Delegate noop})}
{System.showInfo {A operation($)}}

[edit] Pascal

See Delphi

[edit] Perl

Translation of: Python
use strict;
 
package Delegator;
sub new {
bless {}
}
sub operation {
my ($self) = @_;
if (defined $self->{delegate} && $self->{delegate}->can('thing')) {
$self->{delegate}->thing;
} else {
'default implementation';
}
}
1;
 
package Delegate;
sub new {
bless {};
}
sub thing {
'delegate implementation'
}
1;
 
 
package main;
# No delegate
my $a = Delegator->new;
$a->operation eq 'default implementation' or die;
 
# With a delegate that does not implement "thing"
$a->{delegate} = 'A delegate may be any object';
$a->operation eq 'default implementation' or die;
 
# With delegate that implements "thing"
$a->{delegate} = Delegate->new;
$a->operation eq 'delegate implementation' or die;
 

Using Moose.

 
use 5.010_000;
 
package Delegate::Protocol
use Moose::Role;
# All methods in the Protocol is optional
#optional 'thing';
# If we wanted to have a required method, we would state:
# requires 'required_method';
#
 
package Delegate::NoThing;
use Moose;
with 'Delegate::Protocol';
 
package Delegate;
use Moose;
 
# The we confirm to Delegate::Protocol
with 'Delegate::Protocol';
sub thing { 'delegate implementation' };
 
package Delegator;
use Moose;
 
has delegate => (
is => 'rw',
does => 'Delegate::Protocol', # Moose insures that the delegate confirms to the protocol.
predicate => 'hasDelegate'
);
 
sub operation {
 
my ($self) = @_;
if( $self->hasDelegate && $self->delegate->can('thing') ){
return $self->delegate->thing() . $postfix; # we are know that delegate has thing.
} else {
return 'default implementation';
}
};
 
package main;
use strict;
 
# No delegate
my $delegator = Delegator->new();
$delegator->operation eq 'default implementation' or die;
 
# With a delegate that does not implement "thing"
$delegator->delegate( Delegate::NoThing->new );
$delegator->operation eq 'default implementation' or die;
 
# With delegate that implements "thing"
$delegator->delegate( Delegate->new );
$delegator->operation eq 'delegate implementation' or die;
 
 

[edit] Perl 6

class Non-Delegate  { }
 
class Delegate {
method thing {
return "delegate implementation"
}
}
 
class Delegator {
has $.delegate is rw;
 
method operation {
$.delegate.^can( 'thing' ) ?? $.delegate.thing
!! "default implementation"
}
}
 
my Delegator $d .= new;
 
say "empty: "~$d.operation;
 
$d.delegate = Non-Delegate.new;
 
say "Non-Delegate: "~$d.operation;
 
$d.delegate = Delegate.new;
 
say "Delegate: "~$d.operation;

[edit] PHP

Translation of: Python
class Delegator {
function __construct() {
$this->delegate = NULL ;
}
function operation() {
if(method_exists($this->delegate, "thing"))
return $this->delegate->thing() ;
return 'default implementation' ;
}
}
 
class Delegate {
function thing() {
return 'Delegate Implementation' ;
}
}
 
$a = new Delegator() ;
print "{$a->operation()}\n" ;
 
$a->delegate = 'A delegate may be any object' ;
print "{$a->operation()}\n" ;
 
$a->delegate = new Delegate() ;
print "{$a->operation()}\n" ;

[edit] PicoLisp

(class +Delegator)
# delegate
 
(dm operation> ()
(if (: delegate)
(thing> @)
"default implementation" ) )
 
 
(class +Delegate)
# thing
 
(dm T (Msg)
(=: thing Msg) )
 
(dm thing> ()
(: thing) )
 
 
(let A (new '(+Delegator))
# Without a delegate
(println (operation> A))
 
# With delegate that does not implement 'thing>'
(put A 'delegate (new '(+Delegate)))
(println (operation> A))
 
# With delegate that implements 'thing>'
(put A 'delegate (new '(+Delegate) "delegate implementation"))
(println (operation> A)) )

Output:

"default implementation"
NIL
"delegate implementation"

[edit] 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) =>

[edit] Python

class Delegator:
def __init__(self):
self.delegate = None
def operation(self):
if hasattr(self.delegate, 'thing') and callable(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'

[edit] Ruby

Translation of: Python
class Delegator
attr_accessor :delegate
def operation
if @delegate.respond_to?(:thing)
@delegate.thing
else
'default implementation'
end
end
end
 
class Delegate
def thing
'delegate implementation'
end
end
 
if __FILE__ == $PROGRAM_NAME
 
# No delegate
a = Delegator.new
puts a.operation # prints "default implementation"
 
# With a delegate that does not implement "thing"
a.delegate = 'A delegate may be any object'
puts a.operation # prints "default implementation"
 
# With delegate that implements "thing"
a.delegate = Delegate.new
puts a.operation # prints "delegate implementation"
end

Using Forwardable lib

require 'forwardable'
 
class Delegator; extend Forwardable
attr_accessor :delegate
def_delegator :@delegate, :thing, :delegated
 
def initialize
@delegate = Delegate.new()
end
end
 
class Delegate
def thing
'Delegate'
end
end
 
a = Delegator.new
puts a.delegated # prints "Delegate"
 

[edit] Tcl

Works with: Tcl version 8.6
or
Library: TclOO

Uses Assertions#Tcl

package require TclOO
 
oo::class create Delegate {
method thing {} {
return "delegate impl."
}
export thing
}
 
oo::class create Delegator {
variable delegate
constructor args {
my delegate {*}$args
}
 
method delegate args {
if {[llength $args] == 0} {
if {[info exists delegate]} {
return $delegate
}
} elseif {[llength $args] == 1} {
set delegate [lindex $args 0]
} else {
return -code error "wrong # args: should be \"[self] delegate ?target?\""
}
}
 
method operation {} {
try {
set result [$delegate thing]
} on error e {
set result "default implementation"
}
return $result
}
}
 
# to instantiate a named object, use: class create objname; objname aMethod
# to have the class name the object: set obj [class new]; $obj aMethod
 
Delegator create a
set b [Delegator new "not a delegate object"]
set c [Delegator new [Delegate new]]
 
assert {[a operation] eq "default implementation"} ;# a "named" object, hence "a ..."
assert {[$b operation] eq "default implementation"} ;# an "anonymous" object, hence "$b ..."
assert {[$c operation] ne "default implementation"}
 
# now, set a delegate for object a
a delegate [$c delegate]
assert {[a operation] ne "default implementation"}
 
puts "all assertions passed"

To code the operation method without relying on catching an exception, but strictly by using introspection:

method operation {} {
if { [info exists delegate] &&
[info object isa object $delegate] &&
"thing" in [info object methods $delegate -all]
} then {
set result [$delegate thing]
} else {
set result "default implementation"
}
}

[edit] Vorpal

Delegate objects can be an array of delegates or as a single delegate.

a = new()
a.f = method(){
.x.print()
}
 
c = new()
c.g = method(){
(.x + 1).print()
}
 
# array of delegates
b = new()
b.delegate = new()
b.delegate[0] = a
b.delegate[1] = c
b.x = 3
b.f()
b.g()
 
# single delegate
d = new()
d.delegate = a
d.x = 7
d.f()

The resulting output:

3
4
7

[edit] zkl

Translation of: Scala
class Thingable{ var thing; }
 
class Delegator{
var delegate;
fcn operation{
if (delegate) delegate.thing;
else "default implementation"
}
}
 
class Delegate(Thingable){ thing = "delegate implementation" }
    // Without a delegate:
a:= Delegator();
a.operation().println(); //--> "default implementation"
 
// With a delegate:
a.delegate = Delegate();
a.operation().println(); //-->"delegate implementation"

A second example

class [static] Logger{ // Only one logging resource
var [mixin=File] dst; // File like semantics, eg Data, Pipe
dst = File.DevNull;
// initially, the logger does nothing
fcn log(msg){dst.writeln(vm.pasteArgs())}
}
Logger.log("this is a test"); //-->nada
Logger.dst=Console;
Logger.log("this is a test 2"); //-->writes to Console
 
class B(Logger){ log("Hello from ",self,"'s constructor"); }
B(); //-->Hello from Class(B)'s constructor

The base class B was constructed at startup, so the first Hello went to DevNull as all base classes are created before code runs (base classes are used to create class instances, eg B()).

Personal tools
Namespaces

Variants
Actions
Community
Explore
Misc
Toolbox