37

I just recently heard of duck typing and I read the Wikipedia article about it, but I'm having a hard time translating the examples into Java, which would really help my understanding.

Would anyone be able to give a clear example of duck typing in Java and how I might possibly use it?

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Cuga
  • 17,668
  • 31
  • 111
  • 166

10 Answers10

48

Java is by design not fit for duck typing. The way you might choose to do it is reflection:

public void doSomething(Object obj) throws Exception {

    obj.getClass().getMethod("getName", new Class<?>[] {}).invoke(obj);
}

But I would advocate doing it in a dynamic language, such as Groovy, where it makes more sense:

class Duck {
    quack() { println "I am a Duck" }
}

class Frog {
    quack() { println "I am a Frog" }
}

quackers = [ new Duck(), new Frog() ]
for (q in quackers) {
    q.quack()
}

Reference

Robert Munteanu
  • 67,031
  • 36
  • 206
  • 278
  • 2
    ++ Nice duck example, I like the new object creation method. – Secko Jul 03 '09 at 15:27
  • 3
    Came across an elegant library called 'duckapter' if you go down the Java reflection route: http://code.google.com/p/duckapter/ – penfold Oct 03 '12 at 03:29
  • I want to know , why it is hard or impossible to implement duck typing in java or any static type language? People say using interface we can. Plz explain. – kamal Dec 07 '15 at 14:20
11

See this blog post. It gives a very detailed account of how to use dynamic proxies to implement duck typing in Java.

In summary:

  • create an interface that represents the methods you want to use via duck typing
  • create a dynamic proxy that uses this interface and an implementation object that invokes methods of the interface on the underlying object by reflection (assuming the signatures match)
Dean Povey
  • 9,256
  • 1
  • 41
  • 52
  • It's a good article - d'you think you could summarize the solution given here just in case something happens to it? – Shog9 Apr 08 '13 at 18:49
  • 1
    Added a very basic explanation. – Dean Povey Apr 09 '13 at 22:35
  • Duck typing using *dynamic proxies* can be implemented even in a smaller amount of code -- see [this gist](https://gist.github.com/unix-junkie/b9481245904892f07780). Just note that the order in which interfaces implemented by a `Proxy` are listed matters: if incorrect, you'll receive an `java.lang.IllegalArgumentException: object is not an instance of declaring class`. – Bass Nov 19 '15 at 11:27
7

check this library:

interface MyInterface {
    void foo();
    int bar(int x, int y);
    int baz(int x);
}

public class Delegate {
    public int bar() {
        return 42;
    }
}

DuckPrxy duckProxy = new DuckPrxyImpl();
MyInterface prxy = duckProxy.makeProxy(MyInterface.class, new Delegate());
prxy.bar(2, 3); // Will return 42.

With an interface duck typing is simple using a Dynamic Proxy, you should match the method name and return type.

dfa
  • 114,442
  • 31
  • 189
  • 228
  • 1
    It should be noted that this isn't strictly duck typing but using dynamic proxies (which is what this does) is as close as Java can get. – cletus Jul 03 '09 at 15:14
6

Java doesn't implement duck typing.

cd1
  • 15,908
  • 12
  • 46
  • 47
4

With java 8, you have 2 ways:

nº1: if you only need one method, use lambdas

static interface Action { public int act(); }

public int forEachAct(List<Action> actionlist) {
   int total = 0;
   for (Action a : actionList)
       total += a.act();
}

public void example() {
    List<Action> actionList = new ArrayList<>();
    String example = "example";
    actionList.add(example::length);
    forEachAct(actionList);
}

nº2: Use anonymous classes (not very performance-wise, but in some non-critical parts it can be done)

static interface Action {
    public int act();
    public String describe();
}

public void example() {
    List<Action> actionList = new ArrayList<>();
    String example = "example";

    actionList.add(new Action(){
        public int act() { return example.length(); }
        public String describe() { return "Action: " + example; }
    });
}
2

I've written a utility class to dynamically create decorators for an object. You could use it for duck typing: https://gist.github.com/stijnvanbael/5965616

Example:

interface Quacking {
    void quack();
}

class Duck {
    public void quack() { System.out.println("Quack!"); }
}

class Frog {
    public void quack() { System.out.println("Ribbip!"); }
}

Quacking duck = Extenter.extend(new Duck()).as(Quacking.class);
Quacking frog = Extenter.extend(new Frog()).as(Quacking.class);

duck.quack();
frog.quack();

Output:

Quack!
Ribbip!
Stijn Van Bael
  • 4,830
  • 2
  • 32
  • 38
1

Typing in Java is nominal - compatibility is based on names. If you need an examples on how duck-typing (or structural typing) may look like in Java please look at this page: http://whiteoak.sourceforge.net/#Examples which provides examples for program written in Whiteoak: A Java-compatible language that also supports structural typing.

Itay Maman
  • 30,277
  • 10
  • 88
  • 118
1

Typically, duck typing is used with dynamically typed languages. You would check at runtime for the existence of methods or properties that are required to fulfill your needs, regardless of inheritance hierarchies.

Other than using reflection, which would get ugly, the closest you can get is by using minimal interfaces that match the criteria of what you would need for duck typing. This blog post does a good job describing the concept. It loses much of the simplicity of duck typing in python or ruby or javascript, but its actually pretty good practice in Java if you're looking for a high level of reusability.

Russell Leggett
  • 8,795
  • 3
  • 31
  • 45
1

Nice definition:

Objects are polymorphic without being related by a common base class or interface.

Reference

1

Late to the party (as usual), but I wrote a quick class for doing some duck typing myself. See here.

It will only go to interfaces, but for a usage example:

interface Bird {
    void fly();
}

interface Duck extends Bird {
    void quack();
}

class PseudoDuck {
    void fly() {
        System.out.println("Flying");
    }

    void quack() {
        System.out.println("Quacking");
    }
}

class Tester {
    @Test
    void testDuckTyping() {
        final Duck duck
                = DuckTyper.duckType(new PseudoDuck(), Duck.class);
    }
}

Supports default interface methods, parameters, checking Exception types are compatible and will check all methods of the PseudoDuck's class (including private). Haven't done any testing with generic interfaces yet though.

BeUndead
  • 3,463
  • 2
  • 17
  • 21