What's an Example of Duck Typing in Java

What's an example of duck typing in Java?

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

Example of Duck Typing in Java

There is no duck typing in Java as it is in Python. You can use reflection to find if the class has a method you want to call but it is really a hassle.

It looks like that

Class<?> aClass = object.getClass();
try {
Method method = aClass.getMethod("methodName", argType1, argType2);
method.invoke(arg1, arg2)
} catch (NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}

It is also not possible in every environment. If security manager is enabled your code should have sufficient rights to execute the code above. That also adds substantial work.

What is duck typing?

It is a term used in dynamic languages that do not have strong typing.

The idea is that you don't need to specify a type in order to invoke an existing method on an object - if a method is defined on it, you can invoke it.

The name comes from the phrase "If it looks like a duck and quacks like a duck, it's a duck".

Wikipedia has much more information.

Duck typing and (java) interface concept

Duck typing isn't really about checking whether the things you need are there and then using them. Duck typing is about just using what you need.

The in_the_forest function was written by a developer who was thinking about ducks. It was designed to operate on a Duck. A Duck can quack and feathers, so the coder used those features to get the job at hand done. In this case, the fact that a Duck can also swim wasn't used, and wasn't needed.

In a static language like Java, in_the_forest would have been declared to take a Duck. When the coder later discovered that they had a Person (which could also quack and feathers) and wanted to reuse the function, they're out of luck. Is a Person a subclass of Duck? No, that doesn't seem at all appropriate. Is there a QuacksAndFeathers interface? Maybe, if we're lucky. Otherwise we'll have to make one, go modify Duck to implement it, and modify in_the_forest to take a QuacksAndFeathers instead of a Duck. This may be impossible if Duck is in an external library.

In Python, you just pass your Person to in_the_forest and it works. Because it turns out in_the_forest doesn't need a Duck, it just needs a "duck-like" object, and in this case Person is sufficiently duck-like.

game though, needs a different definition of "duck-like", which is slightly stronger. Here, John Smith is out of luck.

Now, it's true that Java would have caught this error at compile time and Python won't. That can be viewed as a disadvantage. The pro-dynamic-typing counter argument is to say that any substantial body of code you write will always contain bugs that no compiler can catch (and to be honest, Java isn't even a particularly good example of a compiler with strong static checks to catch lots of bugs). So you need to test your code to find those bugs. And if you're testing for those bugs, you will trivially find bugs where you passed a Person to a function that needs a Duck. Given that, the dynamic-typist says, a language that tempts you into not testing because it finds some of your trivial bugs is actually a bad thing. And on top of that, it prevents you from doing some really useful things, like reusing the in_the_forest function on a Person.

Personally I'm torn in two directions. I really like Python with its flexible dynamic typing. And I really like Haskell and Mercury for their powerful static type systems. I'm not much of a fan of Java or C++; in my opinion they have all of the bad bits of static typing with few of the good bits.

Implement duck typing using java MethodHandles

When the VM encounters an invokedynamic instruction for the first time it calls a factory method, or 'bootstrap' method, that returns a CallSite object who's target implements the actual functionality. You can implement that yourself using a MutableCallSite that looks up your target method on first invocation and then sets it's own target to the looked up method.

But, this is not enough for your purposes. You want to re-link the call site when you encounter a new receiver type.

Here is an example (that currently only supports findVirtual):

class DuckTypingCallSite extends MutableCallSite {

private static final MethodHandle MH_relink;
private static final MethodHandle MH_isInstance;

static {
try {
MH_relink = lookup().findVirtual(DuckTypingCallSite.class, "link", methodType(Object.class, Object[].class));
MH_isInstance = lookup().findVirtual(Class.class, "isInstance", methodType(boolean.class, Object.class));
} catch (ReflectiveOperationException e) {
throw new InternalError(e);
}
}

private final MethodHandles.Lookup lookup;
private final String methodName;
private final MethodType lookupType;

private DuckTypingCallSite(MethodHandles.Lookup lookup, String methodName, MethodType lookupType) {
super(lookupType.insertParameterTypes(0, Object.class)); // insert receiver
this.lookup = lookup;
this.methodName = methodName;
this.lookupType = lookupType;
}

public static DuckTypingCallSite make(MethodHandles.Lookup lookup, String methodName, MethodType lookupType) {
DuckTypingCallSite cs = new DuckTypingCallSite(lookup, methodName, lookupType);
cs.setTarget(MH_relink.bindTo(cs).asCollector(Object[].class, cs.type().parameterCount()).asType(cs.type()));
return cs;
}

public Object link(Object[] args) throws Throwable {
Object receiver = args[0];
Class<?> holder = receiver.getClass();
MethodHandle target = lookup.findVirtual(holder, methodName, lookupType).asType(type());

MethodHandle test = MH_isInstance.bindTo(holder);
MethodHandle newTarget = guardWithTest(test, target, getTarget());
setTarget(newTarget);

return target.invokeWithArguments(args);
}

}

Before the first invocation, calling the call site's dynamic invoker will jump right into the link method, which will lookup the target method and then invoke that, as well as re-linking the DuckTypingCallSite to basically cache the looked up MethodHandle, guarded by a type check.

After the first invocation, this essentially creates an if/else like this:

if (A.class.isInstance(receiver)) {
// invoke A.foo
} else {
// re-link
}

Then when the second type is encountered it changes to this:

if (B.class.isInstance(receiver)) {
// invoke B.foo
} else if (A.class.isInstance(receiver)) {
// invoke A.foo
} else {
// re-link
}

etc.

And here is an example usage:

public class DuckTyping {

private static final MethodHandle MH_foo = DuckTypingCallSite.make(lookup(), "foo", methodType(void.class)).dynamicInvoker();

private static void foo(Object receiver) {
try {
MH_foo.invokeExact(receiver);
} catch (Throwable throwable) {
throw new IllegalStateException(throwable);
}
}

public static void main(String[] args) {
foo(new A()); // prints "A.foo"
foo(new B()); // prints "B.foo"
}
}

class A {
public void foo() {
System.out.println("A.foo");
}
}

class B {
public void foo() {
System.out.println("B.foo");
}
}

Duck typing and generic programming

I have encountered two different definitions of "Duck Typing". No doubt there are people who will tell you that one of them is "correct" and the other is "incorrect". I merely attempt to document that they're both used rather than tell you that they're both "correct", but personally I see nothing wrong with the broader meaning.

1) runtime-only typing. Type is a property of objects, not variables, and hence necessarily when you come to call a method on an object, or otherwise use properties that it has by virtue of its type, the presence or absence of that method is discovered at runtime[*]. So if it "looks like a duck and quacks like a duck" (i.e. if it turns out to have a quack() function) then it "is" a duck (anyway, you can treat it like one). By this definition of course C++ templates fall at the first hurdle, they use static typing.

2) A name used more generally for the principle that if it looks like a duck and quacks like a duck then it is a duck, to mean any setup in which interfaces are implicitly defined by the operations performed by the consumer of the interface, rather than interfaces being explicitly advertised by the producer (whatever implements the interface). By this definition, C++ templates do use a kind of duck-typing, but whether something "looks like a duck" is determined at compile time, not at runtime, based on its static type rather than its dynamic type. "Check at compile time, can this variable's static type quack?", not "check at runtime, can this object quack?".

The dispute seems to me in effect to be over whether Python "owns" the term, so that only Python-like type systems can be called duck typing, or whether others are free to appropriate the term to mean a similar concept in a different context. Whatever you think it should mean, it seems irresponsible to use a "jokey" term and demand that everyone understands the same formal definition from it. SO is not a suitable forum to tell you what a term "should" mean, unless there's an authoritative source that you're asking about, like a dictionary or any academic papers that define it formally. I think it can tell you what it's actually used to mean.

"Generic programming" can make use of duck typing or not, depending on the exact details. C++ generic containers do use "type 2" duck-typing, because for a general type in C++ it's not guaranteed that you can copy it, compare it, get a hash value, etc. Java generic containers don't, Object has enough methods already to make it hashable etc.

Conversely, I suspect that anything you do that uses duck typing, can reasonably be referred to as "generic programming". So I suppose, in the terms you asked for, GP > DT in that duck typing (either definition) is a strict subset of the vast range of stuff that can be called "generic".

[*] well, in some cases your dynamic language could have some static analysis that proves the case one way or the other, but the language demands the ability to defer this check until runtime for cases where the static analysis cannot conclusively say.

Simulating duck typing in Java

If you know the set of APIs that you want to expose, say you know you want access to a length method and an iterator method, you can define an interface:

public interface TheInterfaceIWant {
int length();
void quack();
}

and you want to be able to use this interface to access corresponding methods on instances that do not implement this interface, you can use Proxy classes : http://download.oracle.com/javase/1.4.2/docs/api/java/lang/reflect/Proxy.html

So you create a proxy

final Object aDuck = ...;
TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
TheInterfaceIWant.class.getClassLoader(),
new Class[] { TheInterfaceIWant.class },
new InvocationHandler() {
public Object invoke(
Object proxy, Method method, Object[] args)
throws Throwable {
return aDuck.getClass().getMethod(
method.getName(), method.getParameterTypes()).invoke(aDuck, args);
}
});

Then you can use the wrapper as you would the duck in a dynamically typed language.

if (aDuckWrapper.length() > 0) {
aDuckWrapper.quack();
}

Here's a full length runnable example that prints "Quack" four times using a wrapper:

import java.lang.reflect.*;

public class Duck {

// The interface we use to access the duck typed object.
public interface TheInterfaceIWant {
int length();
void quack();
}

// The underlying instance that does not implement TheInterfaceIWant!
static final class Foo {
public int length() { return 4; }
public void quack() { System.out.println("Quack"); }
}

public static void main(String[] args) throws Exception {
// Create an instance but cast away all useful type info.
final Object aDuck = new Foo();

TheInterfaceIWant aDuckWrapper = (TheInterfaceIWant) Proxy.newProxyInstance(
TheInterfaceIWant.class.getClassLoader(),
new Class[] { TheInterfaceIWant.class },
new InvocationHandler() {
public Object invoke(
Object proxy, Method method, Object[] args)
throws Throwable {
return aDuck.getClass().getMethod(
method.getName(), method.getParameterTypes()).invoke(aDuck, args);
}
});

for (int n = aDuckWrapper.length(); --n >= 0;) {
// Calling aDuck.quack() here would be invalid since its an Object.
aDuckWrapper.quack();
}
}
}

What is the difference between polymorphism and duck typing?

Polymorphism (in the context of object-oriented programming) means a subclass can override a method of the base class. This means a method of a class can do different things in subclasses. For example: a class Animal can have a method talk() and the subclasses Dog and Cat of Animal can let the method talk() make different sounds.

Duck typing means code will simply accept any object that has a particular method. Let's say we have the following code: animal.quack(). If the given object animal has the method we want to call then we're good (no additional type requirements needed). It does not matter whether animal is actually a Duck or a different animal which also happens to quack. That's why it is called duck typing: if it looks like a duck (e.g., it has a method called quack() then we can act as if that object is a duck).

So are these related? They are simply separate features that a programming language may have. There are programming languages which have polymorphism but that do not have duck typing (such as Java). There are also languages that have polymorphism and duck typing (such as Python).

What's an example of duck typing in Java?

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

Using Java and C#'s generics to simulate duck typing

can C#'s generics actually achieve the same thing as duck typing?

No. But C#'s generics can include a constraint where the type parameter is restricted to inherit or implement some particular type. When that's done, any expression of the type of that type parameter is resolved as the constrained type and members from that type can be accessed.

This is similar to the extends constraint described in the article you read.

The only duck-typing support in C# is the dynamic keyword, where final compilation of expressions involving dynamic values is deferred until runtime when the actual runtime type is known.

Related reading:

Trivial C# class with a generic parameter wouldn't compile for no apparent reason

Call a method of type parameter



Related Topics



Leave a reply



Submit