Go Does Delegates Beautifully!

When working with object-oriented languages, there are many instances when one would want to implement an interface re-using code from another implementation of the interface. While inheritance will work, it couples the new implementation to the specific other implementation. Composition with delegation will be a better way of doing this.

Let’s consider an application which deals with doors of different shapes. You’d have a Door type and a Shape interface implemented by different concrete shapes. You’d also have a DrawingSurface which takes any implementation of Shape and invokes draw() and fill() on it passing a graphics context.

Here’s the verbose and repetitive code you’d have in Java with neither delegates nor any form of duck-typing.

interface Shape {
    public void draw(GContext ctx);
    public void fill(GContext ctx);
}

class Door implements Shape {
    private Shape shape;

    public Door(Shape shape) {
        this.shape = shape;
    }

    public void draw(GContext ctx) {
        shape.draw(ctx);
    }

    public void fill(GContext ctx) {
        shape.draw(ctx);
    }
}

In a dynamic language with meta-programming like Ruby, this is less verbose but the delegates still need to be explicitly defined. The forwardable library defines the specified methods on Door to invoke corresponding methods on @shape at run-time. However, tools like IDEs can’t recognize Door as an implementation of Shape unless they handle the specific library call as a special case.

require 'forwardable'

class Door
    def_delegators :@shape, :draw, :fill

    def initialize(shape)
        @shape = shape
    end
end

Go gives you delegates with no extra work. You just say Door has a Shape and you get statically checked and compiled delegation.

type Shape interface {
    draw(ctx GContext)
    fill(ctx GContext)
}

type Door struct {
    Shape
}

This has all the compile-time safety checks of Java with the expressiveness of Ruby. This is one of the many cases where Go’s simple design makes code less verbose!

06 Apr, 2012 golang / ruby / delegates / java