duck<T>()

The duck<T>()function allows you to apply Duck Typing to let the compiler treat an object as compatible to an interface (or protocol, in Swift parlance), even though the object does not formally implement the interface.

Syntax:

method duck<T>(anObject: Object; mode: DuckTypingMode := DuckTypingMode.Static): T;
T duck<T>(object anObject, DuckTypingMode mode = DuckTypingMode.Static);
func duck<T>(_ anObject: AnyObject!, _ mode: DuckTypingMode = DuckTypingMode.Static) -> T
T duck<T>(Object anObject, DuckTypingMode mode = DuckTypingMode.Static);

In the example below, you can convert a FooBar object instance to an IFooBar, even though the class does not implement IFooBar. For example, you could write:

type
  FooBar = class
  public
    method Test;
  end;

  IFooBar = interface
    method Test;
  end;

  method RunTest(aObject:IFooBar); // ...

var fb := new FooBar();
RunTest(duck<IFooBar>(fb));
class FooBar
{
    void Test() {}
}

interface IFooBar
{
    void Test() {}
}

void RunTest(IFooBar aObject) { ... }

FooBar fb = new FooBar();
RunTest(duck<IFooBar>(fb));
class FooBar {
    func Test() {
    }
}

interface IFooBar {
    func Test() {
    }
}

void RunTest(IFooBar aObject) { ... }

let fb:Foobar = FooBar()
RunTest(duck<IFooBar>(fb))
class FooBar {
    void Test() {}
}

interface IFooBar {
    void Test() {}
}

void RunTest(IFooBar aObject) { ... }

FooBar fb = new FooBar();
RunTest(duck<IFooBar>(fb));

Even though the class does not implement the IFooBar type, the compiler will build a bridge to let you call it.

Duck Typing Modes

In the default Static mode, the compiler will emit an error if any of the methods aren't implemented. Optionally, a DuckTypingMode mode can be passed as second parameter. This enum type has the following three members:

  • *DuckTypingMode.Static: The default. It binds all methods and fails at compile time if the target doesn't implement it.
  • DuckTypingMode.Weak: Fails at runtime for any call that the target class does not implement (useful if you know your code will only call valid members).
  • DuckTypingMode.Dynamic: Uses dynamic dispatch to execute the method.

duck() and Type Casts on Cocoa

Objective-C allows more lenient casting of objects, and as long as the methods that are being called on the cast object exist, they can be called even if the object and the interface (or the to class types) were not really compatible.

By contrast, all casts done by the Elements compiler are strict, and result in either nil or an exception if the two types being cast were not compatible.

Using the duck<T>() method on Cocoa can be thought of as the equivalent of Objective-C unsafe typecast, and can be used to cast any Cocoa object instance to any other Cocoa class or interface/protocol.

See Also