Duck typing in java
Tags: java, experiment, fun
Published: 2019-04-09 20:12:04

---
title: Duck typing in java
published: true
cover_image: https://thepracticaldev.s3.amazonaws.com/i/yd4yqayn4cat53gfxk2z.jpg
description: Creating dynamic proxies to simulate duck typing in java
tags: java,experiment,fun
---

Disclaimer: please don't take this too serious. It's just fun and games.

_Duck typing_ is an idiom known mostly from dynamically typed languages. It states that you can treat unrelated Objects of type X as Objects of type Y as long as both have the same public interface.

> If it looks like duck, moves like duck and makes sounds like a duck then it must be a duck!

Java's static type system on the other hand, imposes strong rules on type compatibility. Just having the same methods doesn't qualify two classes to be _"type compatible"_. Consider this example:

```java
public class Duck {
    public String makeNoise() {
        return "Quak Quak";
    }
}

public class Dog {
    public String makeNoise() {
        return "woof woof";
    }
}

```

Both classes have the same interface, so can we assign instances to the respective other type?

```java
final Duck duck = new Dog(); // fails
assertEquals("woof woof", duck.makeNoise());
```

Of course we can't. Java's type system needs explicit definitions of compatible classes using inheritance. 

Let's now make our example work using the easiest imaginable change to our code:

```java
public class Dog extends Duck {
    @Override
    public String makeNoise() {
        return "woof woof";
    }
}
```
Besides everything you learned in biology classes our `Dog` now _is a_ duck and is thereby assignable to variables with type `Duck`. This change should have made the test above turn green.

Ok, now our Dog is a Duck, but what about all the other classes in our code base that also have a `makeNoise` method? Should they all extend the `Duck` class? That seems impractical and confusing (`class Train extends Duck` is even stranger than a Dog being a Duck). 

Maybe we can build a more dynamic Duck by using _reflection_. During runtime the JVM has pretty extensive type information about every object. Besides accessing type information, reflection also allows us to dynamically retrieve and call methods on arbitrary objects. 

```java
public class DynamicDuck extends Duck {

    private final Object notADuck;

    public DynamicDuck(Object notADuck) {
        this.notADuck = notADuck;
    }

    @Override
    public String makeNoise() {
        // try block is needed because the reflection stuff will 
        // throw all kind of horrible exceptions if you use it wrong
        try {
            // retrieve dynamic type information of the non-duck object
            final Class<?> notADuckType = this.notADuck.getClass();

            // find the method of the class that is not a duck by name
            final Method delegate = notADuckType.getMethod("makeNoise");

            // invoke the method on the object that is not a duck
            return (String) delegate.invoke(this.notADuck);
        } catch (Exception e) {
            throw new IllegalStateException("DynamicDuck error");
        }
    }
}
```

Using our `DynamicDuck` we can get a "duck-view" on every non-duck Object. Let's adjust our initial test accordingly (and also remove the `extends` clause in the `Dog` class):

```java
final Duck duck = new DynamicDuck(new Dog());
assertEquals("woof woof", duck.makeNoise());
```

That's a little more dynamic but still doesn't scale well. If the `Duck` class had more public methods we'd have to delegate _every_ method to the non-duck Object like we did above. And if we decided not to view everything as a Duck, but as a Goose, we need to additionally create a `DynamicGoose` class. That's all way too cumbersome.

Luckily, Java has another useful concept that comes in handy for our use case. Every class that is available during runtime will be loaded from its byte code representation using a `ClassLoader`. As this is a pure runtime feature you can make up artificial classes during runtime that did not exist during compile time.

We can dynamically generate the byte code of a class that `extends Duck` and which automatically delegates every called method to the equivalent method of an arbitrary non-duck Object. The following code uses the popular libraries _cglib_ (for byte code generation) and _Objenesis_ (for instantiating the dynamically generated classes.

```java
import net.sf.cglib.core.DefaultNamingPolicy;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.InvocationHandler;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;

import java.lang.reflect.Method;

public class NotADuck {
    /**
     * The unique callback index to which each method in the proxy object is mapped.
     */
    private static final int CALLBACK_INDEX = 0;

    /**
     * Maps all methods to index {@link #CALLBACK_INDEX}.
     */
    private static final CallbackFilter ZERO_CALLBACK_FILTER = method -> CALLBACK_INDEX;

    // with caching
    private static final Objenesis OBJENESIS = new ObjenesisStd(true);

    public static <T> T asDuck(Object notADuck, Class<T> type) {
        final Enhancer enhancer = new Enhancer();
        final InvocationHandler invocationHandler = new DelegateDuckToNonDuckMethod(notADuck);

        enhancer.setSuperclass(type);
        enhancer.setUseFactory(true);
        enhancer.setNamingPolicy(new DefaultNamingPolicy());
        enhancer.setCallbackFilter(ZERO_CALLBACK_FILTER);
        enhancer.setCallbackType(invocationHandler.getClass());

        final Class<T> proxyClass = enhancer.createClass();
        final T duckInstance = OBJENESIS.getInstantiatorOf(proxyClass).newInstance();
        final Factory factory = (Factory) duckInstance;
        factory.setCallback(CALLBACK_INDEX, invocationHandler);
        return duckInstance;
    }

    private static class DelegateDuckToNonDuckMethod implements InvocationHandler {

        private final Object notADuck;

        private DelegateDuckToNonDuckMethod(Object notADuck) {
            this.notADuck = notADuck;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            final Method nonDuckMethod = notADuck.getClass().getMethod(method.getName(), method.getParameterTypes());
            return nonDuckMethod.invoke(notADuck, args);
        }
    }
}

```

Using this class, we can create a dynamic, duck-view of a Dog instance:

```java
final Duck duck = NotADuck.asDuck(new Dog(), Duck.class);
assertEquals("woof woof", duck.makeNoise());
```

The code is no longer restricted to only create `Duck` objects:

```java
List list = NotADuck.asDuck("I'm a String", List.class);
// both List and String have an isEmpty method
assertFalse(list.isEmpty());
```

This was just a little experiment. There are likely bugs, uncovered edge cases, performance issues and general lack of practical use cases in this implementation. Nevertheless it's fun to see how far you can go with Java's dynamic type information and materialization of arbitrary byte code.

**Don't do this at home!**