Delegates: Difference between revisions
Content deleted Content added
Added Wren |
Added FreeBASIC |
||
(12 intermediate revisions by 5 users not shown) | |||
Line 16:
=={{header|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.
<
procedure Delegation is
Line 63:
A.Delegate := Has_Thing'Access; -- Set a thing
Put_Line (A.Operation);
end Delegation;</
Sample output:
<pre>
Line 72:
=={{header|Aikido}}==
<
class Delegator {
public generic delegate = none
Line 97:
println (d1.operation())
</syntaxhighlight>
=={{header|Aime}}==
<
thing(void)
{
Line 141:
return 0;
}</
=={{header|ALGOL 68}}==
As Algol 68 doesn't have classes, we supply a non-OO approximation, similar to the C version.
<
# The delegate mode - the delegate is a STRUCT with a single field #
Line 220:
)
</syntaxhighlight>
{{out}}<pre>
No delegate : default implementation
Line 229:
=={{header|Atari Basic}}==
The code does not fully implement all requirements from above.
If you find which requirements have not been met that's great.
What is your proposal to solve that in the code?
<syntaxhighlight lang="ataribasic">
10 REM DELEGATION CODE AND EXAMPLE . ATARI BASIC 2020 A. KRESS andreas.kress@hood-group.com
14 REM
15 GOTO 100:REM MAINLOOP
Line 242 ⟶ 247:
56 RETURN
60 REM CALL DELEGATE
65 GOSUB
66 RETURN
79 REM
Line 256 ⟶ 261:
130 DELEGATE=80:REM DELEGATE IS
140 GOSUB 20:REM INIT DELEGATOR
</syntaxhighlight>
{{out}}<pre>
RUN
Line 267 ⟶ 272:
=={{header|C}}==
As best you can do, without support for classes.
<
#include <stdlib.h>
#include <string.h>
Line 352 ⟶ 357:
Delegator_Operation( theDelegator, 3, del2));
return 0;
}</
=={{header|C sharp|C#}}==
<
interface IOperable
Line 393 ⟶ 398:
}
}
}</
Output:
<pre>Default implementation.
Line 402 ⟶ 407:
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.
<syntaxhighlight lang="cpp">
#include <tr1/memory>
#include <string>
Line 482 ⟶ 487:
*/
}
</syntaxhighlight>
=={{header|Clojure}}==
<
(thing [_]))
Line 497 ⟶ 502:
(defrecord Delegate []
Thing
(thing [_] "delegate implementation"))</
{{out}}
Line 516 ⟶ 521:
=={{header|CoffeeScript}}==
{{trans|Python}}
<
class Delegator
operation: ->
Line 541 ⟶ 546:
testDelegator()
</syntaxhighlight>
output
<syntaxhighlight lang="text">
> coffee foo.coffee
default implementation
default implementation
Delegate Implementation
</syntaxhighlight>
=={{header|Common Lisp}}==
Line 555 ⟶ 560:
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.
<
(:documentation "Thing the object."))
Line 583 ⟶ 588:
(assert (string= "no delegate" (thing d1)))
(assert (string= "default implementation" (thing d2)))
(assert (string= "delegate implementation" (thing d3))))</
=={{header|D}}==
Line 589 ⟶ 594:
''Delegate'' object and pass a real delegate directly to '''Delegator'''.
<
string delegate() hasDelegate;
Line 612 ⟶ 617:
writeln(dr.operation());
writeln(dr.setDg(thing).operation());
}</
{{out}}
<pre>Default implementation
Line 620 ⟶ 625:
===Version using Tango===
{{libheader|tango}}
<
class Delegator
Line 648 ⟶ 653:
Stdout ( dr.setDg(thing).operation ).newline;
return 0;
}</
=={{header|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
<
var delegate;
Line 680 ⟶ 685:
a.delegate = d;
Expect.equals("delegate implementation",a.operation());
}</
=={{header|Delphi}}==
Translation of the Java example found at [http://en.wikipedia.org/wiki/Delegation_pattern Wikipedia].
<
interface
Line 733 ⟶ 738:
end;
end.</
<
{$APPTYPE CONSOLE}
Line 752 ⟶ 757:
PrinterObj.Free;
end;
end.</
=={{header|E}}==
<
/** construct without an explicit delegate */
to run() {
Line 789 ⟶ 794:
> })
> delegator.operation()
# value: "default implementation"</
=={{header|Elena}}==
ELENA
Using multi methods:
<
import system'routines;
interface IOperable
{
abstract operate()
}
Line 834 ⟶ 839:
var delegator := new Delegator();
new object[]{nil, new Object(), new Operable()}.forEach::(o)
{
delegator.Delegate := o;
Line 840 ⟶ 845:
console.printLine(delegator.operate())
}
}</
Generic solution:
<
import system'routines;
Line 855 ⟶ 860:
class Delegator
{
constructor()
Line 864 ⟶ 869:
operate()
{
// if the object does not support "
var operable := Delegate.Operable \ back
if (nil == operable)
Line 882 ⟶ 887:
var delegator := new Delegator();
new object[]{nil, new Object(), new Operable()}.forEach::(o)
{
delegator.Delegate := o;
Line 888 ⟶ 893:
console.printLine(delegator.operate())
}
}</
{{out}}
<pre>
Line 895 ⟶ 900:
delegate implementation
</pre>
=={{header|FreeBASIC}}==
{{trans|Phix}}
FreeBASIC does not directly support objects or delegation functions. However, you can achieve similar functionality using user-defined types and function pointers.
<syntaxhighlight lang="vbnet">
Type Objeto
operation As Function() As String
other As String
End Type
Function xthing() As String
Return "default implementation"
End Function
Function newX() As Objeto
Dim As Objeto o
o.operation = @xthing
Return o
End Function
Function newY() As Objeto
Dim As Objeto o = newX()
o.other = "something else"
o.operation = 0 ' remove delegate
Return o
End Function
Function zthing() As String
Return "delegate implementation"
End Function
Function newZ() As Objeto
Dim As Objeto o = newX()
o.operation = @zthing ' replace delegate
Return o
End Function
Function operation(o As Objeto) As String
Return Iif(o.operation <> 0, o.operation(), "no implementation")
End Function
Dim As Objeto x = newX()
Dim As Objeto y = newY()
Dim As Objeto z = newZ()
Print operation(x)
Print operation(y)
Print operation(z)
Sleep</syntaxhighlight>
{{out}}
<pre>Similar as Phix entry.</pre>
=={{header|F_Sharp|F#}}==
<
let defaultOperation() = "default implementation"
let mutable del = null
Line 922 ⟶ 979:
d.Delegate <- new Delegate()
assert (d.operation() = "delegate implementation")</
=={{header|Forth}}==
Line 930 ⟶ 987:
Needs the FMS-SI (single inheritance) library code located here:
http://soton.mpeforth.com/flag/fms/index.html
<
:class delegate
Line 964 ⟶ 1,021:
slave master !:
master operation \ => delegate implementation
</syntaxhighlight>
=={{header|Go}}==
<
import "fmt"
Line 1,006 ⟶ 1,063:
a.delegate = d
fmt.Println(a.operation()) // prints "delegate implementation"
}</
=={{header|Io}}==
{{trans|Python}}
<
delegate ::= nil
operation := method(
Line 1,031 ⟶ 1,088:
a setDelegate(Delegate clone)
a operation println</
{{out}}
<pre>default implementation
Line 1,041 ⟶ 1,098:
Life becomes slightly cleaner if we delegate to ourselves in the absence of some other delegate.
<
operation=:3 :'thing__delegate ::thing y'
thing=: 'default implementation'"_
Line 1,053 ⟶ 1,110:
NB. set context in case this script was used interactively, instead of being loaded
cocurrent 'base'</
Example use:
<
operation__obj''
default implementation
Line 1,071 ⟶ 1,128:
└─┘
operation__obj''
delegate implementation</
=={{header|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.
<
String thing();
}
Line 1,118 ⟶ 1,175:
assert a.operation().equals("anonymous delegate implementation");
}
}</
{{works with|Java|8+}}
<
@FunctionalInterface
public interface Thingable {
public String thing();
}</
<
import java.util.Optional;
Line 1,146 ⟶ 1,203:
;
}
}</
<
@FunctionalInterface
Line 1,164 ⟶ 1,221:
return () -> thingable;
}
}</
<
public final class Delegate implements Thingable {
Line 1,173 ⟶ 1,230:
return "delegate implementation";
}
}</
<
// Example usage
Line 1,210 ⟶ 1,267:
assert d5.operation().equals("lambda expression implementation");
}
}</
=={{header|JavaScript}}==
{{trans|Python}}
<
this.delegate = null ;
this.operation = function(){
Line 1,238 ⟶ 1,295:
a.delegate = new Delegate() ;
document.write(a.operation() + "\n") ;
}</
=={{header|Julia}}==
'''Module''':
<
export Delegator, Delegate
Line 1,256 ⟶ 1,313:
thing(::Delegate) = "delegate implementation"
end # module Delegates</
'''Main''':
<
a = Delegator(nothing)
Line 1,269 ⟶ 1,326:
@show Delegates.operation(a)
@show Delegates.operation(b)
@show Delegates.operation(c)</
{{out}}
Line 1,280 ⟶ 1,337:
The first two scenarios are not therefore strictly possible though the second can be simulated by passing a 'responds' parameter to the delegate class constructor.
<
interface Thingable {
Line 1,304 ⟶ 1,361:
val dd2 = Delegator(d2)
println(dd2.operation())
}</
{{out}}
Line 1,315 ⟶ 1,372:
{{trans|Python}}
<
self delegate := Nil.
self clone := {
Line 1,346 ⟶ 1,403:
;; Delegate which implements `thing`
foo delegate := Delegate.
println: foo operation. ;; "delegate implementation"</
=={{header|Logtalk}}==
We use prototypes instead of classes for simplicity.
<
% and implementation for delegator objects
Line 1,425 ⟶ 1,482:
a_delegator::operation(String3),
String3 == 'delegate implementation'
)).</
=={{header|Lua}}==
<
return {
operation = function(self)
Line 1,473 ⟶ 1,530:
assert(d:operation() == "delegate implementation")
print("pass")</
=={{header|M2000 Interpreter}}==
<syntaxhighlight lang="m2000 interpreter">
Module Checkit {
\\ there are some kinds of objects in M2000, one of them is the Group, the user object
Line 1,584 ⟶ 1,641:
Checkit
</syntaxhighlight>
{{out}}
<pre>
Line 1,615 ⟶ 1,672:
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<
If[StringQ[del@operate], del@operate, "default implementation"];
del1 = Null;
del2@banana = "phone";
del3@operate = "delegate implementation";
Print[delegator[#]@operate] & /@ {del1, del2, del3};</
{{out}}
<pre>default implementation
Line 1,627 ⟶ 1,684:
=={{header|NGS}}==
<syntaxhighlight lang="ngs">{
type Delegator
Line 1,666 ⟶ 1,723:
echo(a.operation())
}</
{{out}}
<pre>default implementation
Line 1,673 ⟶ 1,730:
=={{header|Nim}}==
<
# Base delegate.
Line 1,720 ⟶ 1,777:
let d2 = initDelegator(Delegate2())
echo "With a delegate which provided the “thing” method: ", d2.operation()</
{{out}}
Line 1,729 ⟶ 1,786:
=={{header|Objeck}}==
{{trans|Java}}
<
method : virtual : public : Thing() ~ String;
}
Line 1,783 ⟶ 1,840:
}
}
</syntaxhighlight>
=={{header|Objective-C}}==
Line 1,789 ⟶ 1,846:
{{works with|Cocoa}}
{{works with|GNUstep}}
<
@interface Delegator : NSObject {
Line 1,864 ⟶ 1,921:
return 0;
}</
Objective-C 2.0, modern runtime, Automatic Reference Counting, Autosynthesize (LLVM 4.0+)
{{works with|Cocoa}}
<
// Formal protocol for the delegate
Line 1,913 ⟶ 1,970:
}
return 0;
}</
=={{header|Oforth}}==
<
Object Class new: Delegate2
Line 1,926 ⟶ 1,983:
Delegator method: operation
@delegate respondTo(#thing) ifTrue: [ @delegate thing return ]
"Default implementation" println ;</
Usage :
<
Default implementation
Line 1,936 ⟶ 1,993:
Delegator new(Delegate2 new) operation
Delegate implementation</
=={{header|ooRexx}}==
<syntaxhighlight lang="oorexx">
delegator = .delegator~new -- no delegate
say delegator~operation
Line 1,980 ⟶ 2,037:
nomethod:
return "default implementation"
</syntaxhighlight>
=={{header|OxygenBasic}}==
<
class DelegateA 'not implmenting thing()
'==============
Line 2,028 ⟶ 2,085:
print dgr.thing 'result "not using Delegate"
print dg.thing 'result "Delegate Implementation"
</syntaxhighlight>
=={{header|Oz}}==
{{trans|Python}}
<
class Delegator from BaseObject
attr
Line 2,074 ⟶ 2,131:
{A set({New Delegate noop})}
{System.showInfo {A operation($)}}</
=={{header|Pascal}}==
Line 2,081 ⟶ 2,138:
=={{header|Perl}}==
{{trans|Python}}
<
package Delegator;
Line 2,119 ⟶ 2,176:
$a->{delegate} = Delegate->new;
$a->operation eq 'delegate implementation' or die;
</syntaxhighlight>
Using Moose.
<
use 5.010_000;
Line 2,179 ⟶ 2,236:
$delegator->operation eq 'delegate implementation' or die;
</syntaxhighlight>
=={{header|Phix}}==
Line 2,185 ⟶ 2,242:
I will admit that the whole concept of "no delegate/with one that does not implement" makes no sense whatsoever to me.<br>
While I've shown this using a single rid, you could of course hold an entire sequence of them or even better a dictionary and use named lookups for rids in that.
<
function operation(object o)
Line 2,228 ⟶ 2,285:
?operation(x)
?operation(y)
?operation(z)</
{{out}}
Line 2,237 ⟶ 2,294:
</pre>
Obviously, you can explictly test for rid=NULL as shown, or remove that test and catch exceptions, ie:
<
try -- (since rid=NULL check commented out)
?operation(y)
Line 2,243 ⟶ 2,300:
?"oops, no implementation"
end try
?operation(z)</
=={{header|PHP}}==
{{trans|Python}}
<
function __construct() {
$this->delegate = NULL ;
Line 2,271 ⟶ 2,328:
$a->delegate = new Delegate() ;
print "{$a->operation()}\n" ;</
=={{header|PicoLisp}}==
<
# delegate
Line 2,303 ⟶ 2,360:
# With delegate that implements 'thing>'
(put A 'delegate (new '(+Delegate) "delegate implementation"))
(println (operation> A)) )</
Output:
<pre>"default implementation"
Line 2,310 ⟶ 2,367:
=={{header|Pop11}}==
<
define :class Delegator;
slot delegate = false;
Line 2,341 ⟶ 2,398:
;;; delegating to a freshly created Delegate
newDelegate() -> delegate(a);
operation(a) =></
=={{header|Python}}==
<
def __init__(self):
self.delegate = None
Line 2,368 ⟶ 2,425:
# With delegate that implements "thing"
a.delegate = Delegate()
assert a.operation() == 'delegate implementation'</
=={{header|Racket}}==
Line 2,380 ⟶ 2,437:
follows the requirement of the task better.
<
;; Delegates. Tim Brown 2014-10-16
Line 2,414 ⟶ 2,471:
(send delegator-2 operation) => "delegate implementation"
(send (new delegator% [delegate thinging-delegate]) operation) => "delegate implementation"))
</syntaxhighlight>
All the tests pass. Believe me.
Line 2,420 ⟶ 2,477:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku"
class Delegate {
Line 2,447 ⟶ 2,504:
$d.delegate = Delegate.new;
say "Delegate: "~$d.operation;</
=={{header|Ruby}}==
{{trans|Python}}
<
attr_accessor :delegate
def operation
Line 2,481 ⟶ 2,538:
a.delegate = Delegate.new
puts a.operation # prints "delegate implementation"
end</
Using Forwardable lib
<
class Delegator; extend Forwardable
Line 2,504 ⟶ 2,561:
a = Delegator.new
puts a.delegated # prints "Delegate"
</syntaxhighlight>
=={{header|Rust}}==
Requiring delegates to implement Thingable:
<
fn thing(&self) -> &str;
}
Line 2,534 ⟶ 2,591:
let d: Delegator<Delegate> = Delegator(Some(Delegate {}));
println!("{}", d.thing());
}</
{{Out}}
<pre>Default implmementation
Line 2,540 ⟶ 2,597:
Using nightly-only specialization feature:
<
trait Thingable {
Line 2,580 ⟶ 2,637:
let d: Delegator<Delegate> = Delegator(Some(Delegate {}));
println!("{}", d.thing());
}</
{{Out}}
<pre>Default implementation
Line 2,589 ⟶ 2,646:
=={{header|Scala}}==
{{Out}}Best seen running in your browser either by [https://scalafiddle.io/sf/cCYD9tQ/0 ScalaFiddle (ES aka JavaScript, non JVM)] or [https://scastie.scala-lang.org/2TWYJifpTuOVhrAfWP51oA Scastie (remote JVM)].
<
def thing: String
}
Line 2,620 ⟶ 2,677:
assert(a.operation == "anonymous delegate implementation")
}</
=={{header|Sidef}}==
<
class Delegate {
Line 2,647 ⟶ 2,704:
say "NonDelegate: #{d.operation}"
d.delegate = Delegate()
say "Delegate: #{d.operation}"</
{{out}}
empty: default implementation
Line 2,656 ⟶ 2,713:
{{works with|Smalltalk/X}}
Definition of the thingy:
<
subclass:#Thingy
instanceVariableNames:''
thing
^ 'thingy implementation'</
Definition of the delegator:
<
subclass:#Delegator
instanceVariableNames:'delegate'
Line 2,672 ⟶ 2,729:
operation
^ delegate
perform:#thing ifNotUnderstood:'default implementation'.</
Sample use:
<
d := Delegator new.
d operation.
Line 2,681 ⟶ 2,738:
d delegate:(Thingy new).
d operation.
-> 'thingy implementation'</
=={{header|Swift}}==
Allowing the delegate to be any type and taking advantage of dynamism of method lookup:
<
protocol Thingable { // prior to Swift 1.2, needs to be declared @objc
Line 2,717 ⟶ 2,774:
let d = Delegate()
a.delegate = d
println(a.operation()) // prints "delegate implementation"</
Alternately, requiring the delegate to conform to a given protocol:
<
func thing() -> String
}
Line 2,747 ⟶ 2,804:
let d = Delegate()
a.delegate = d
println(a.operation()) // prints "delegate implementation"</
=={{header|Tcl}}==
{{works with|Tcl|8.6}} or {{libheader|TclOO}}
Uses [[Assertions#Tcl]]
<
oo::class create Delegate {
Line 2,804 ⟶ 2,861:
assert {[a operation] ne "default implementation"}
puts "all assertions passed"</
To code the <code>operation</code> method without relying on catching an exception, but strictly by using introspection:
<
if { [info exists delegate] &&
[info object isa object $delegate] &&
Line 2,816 ⟶ 2,873:
set result "default implementation"
}
}</
=={{header|TXR}}==
<syntaxhighlight lang="txrlisp">;; TXR Lisp's :delegate implementation is hard delegation: the indicated
;; delegate object must exist and take the method call. To do soft
;; delegation, we develop a macro (delegate-or-fallback x y z)
;; which chooses x if x is an object which supports a z method,
;; or else chooses y.
(defun delegate-or-fallback-impl (del-inst fb-inst required-meth)
(let (del-type)
(if (and (structp del-inst)
(set del-type (struct-type del-inst))
(static-slot-p del-type required-meth)
(functionp (static-slot del-type required-meth)))
del-inst
fb-inst)))
(defmacro delegate-or-fallback (delegate-expr fallback-obj : required-meth)
^(delegate-or-fallback-impl ,delegate-expr ,fallback-obj ',required-meth))
;; With the above, we can use the defstruct delegate clause syntax:
;;
;; (:delegate source-method (obj) target-obj target-method)
;;
;; which writes a delegate method called source-method, that delegates
;; to target-method on target-obj. We calculate target-obj using
;; our macro and ensure that the delegator itself imlpements target-method.
(defstruct delegator ()
delegate
(:delegate operation (me) (delegate-or-fallback me.delegate me thing) thing)
(:method thing (me)
"default implementation"))
(defstruct delegate ()
(:method thing (me)
"delegate implementation"))
;; Tests:
;; no delegate
(prinl (new delegator).(operation))
;; struct delegate, but not with thing method
(prinl (new delegator delegate (new time)).(operation))
;; delegate with thing method
(prinl (new delegator delegate (new delegate)).(operation))</syntaxhighlight>
{{out}}
<pre>"default implementation"
"default implementation"
"delegate implementation"</pre>
=={{header|Vorpal}}==
Delegate objects can be an array of delegates or as a single delegate.
<
a.f = method(){
.x.print()
Line 2,843 ⟶ 2,956:
d.delegate = a
d.x = 7
d.f()</
The resulting output:
Line 2,854 ⟶ 2,967:
=={{header|Wren}}==
Wren is dynamically typed so we can plug any kind of delegate into the Delegator.
<
thing { }
}
Line 2,894 ⟶ 3,007:
// with a delegate that does implement Thingable
d.delegate = Delegate2.new()
System.print(d.operation)</
{{out}}
Line 2,905 ⟶ 3,018:
=={{header|zkl}}==
{{trans|Scala}}
<
class Delegator{
Line 2,915 ⟶ 3,028:
}
class Delegate(Thingable){ thing = "delegate implementation" }</
<
a:= Delegator();
a.operation().println(); //--> "default implementation"
Line 2,923 ⟶ 3,036:
// With a delegate:
a.delegate = Delegate();
a.operation().println(); //-->"delegate implementation"</
A second example
<
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.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,
|