Reputation: 17904
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?
Upvotes: 39
Views: 25554
Reputation: 1
Actually it exists in a way:
class Scratch {
interface Duck{
String quack(String name);
}
interface Frog{
String croak(String name);
}
public static void main(String[] args) {
Duck duck = Scratch::sound;
Frog frog = Scratch::sound;
Frog frog2 = duck::quack;
duck.quack("Duck");
frog.croak("Frog");
frog2.croak("who knows");
}
public static String sound(String name){
return "I am "+ name;
}
}
Upvotes: 0
Reputation: 3618
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.
Upvotes: 1
Reputation: 4850
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!
Upvotes: 2
Reputation: 5655
Nice definition:
Objects are polymorphic without being related by a common base class or interface.
Upvotes: 1
Reputation: 127
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; }
});
}
Upvotes: 5
Reputation: 9446
See this blog post. It gives a very detailed account of how to use dynamic proxies to implement duck typing in Java.
In summary:
Upvotes: 11
Reputation: 8883
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.
Upvotes: 1
Reputation: 30723
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.
Upvotes: 1
Reputation: 68268
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()
}
Upvotes: 49
Reputation: 116334
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.
Upvotes: 7