すでに与えられた答えのほとんどは正しいです。オブジェクトがインターフェースを実装する場合、そのインターフェースの実装が必要な場所ならどこでもそのオブジェクトを使用できます。これは、Java の強力な型付けシステムを考えると、最も自然なアプローチです。
List
/の例を維持するために、オブジェクトをArrayList
作成し、それを必要な場所ならどこでも使用できます。または、他の実装されたインターフェイスに基づいて、、、、、または スーパークラスを考慮すると、 のインスタンスは、、またはとして使用できます。ArrayList
List
Serializable
Cloneable
Iterable
Collection
RandomAccess
ArrayList
AbstractList
AbstractCollection
java.lang.Object
リフレクションをダイナミック プロキシ オブジェクトと共に使用して、正しいメソッドを持つオブジェクトをアヒルのコスチュームにくさびで留めることができます。これにより、型チェックがランタイムに移行し、通常は、通常の型付けシステムに反対するよりも、それを使用するほうがはるかに優れた理由があります。
面白そうなので、Duck 以外のオブジェクトをプロキシ オブジェクトでラップする例を次に示します。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DuckDemo {
public static Duck getDuckProxy(final Object duckLike) {
final InvocationHandler invocationHandler = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Class<?> actualClass = duckLike.getClass();
String methodName = method.getName();
Class[] parameterTypes = method.getParameterTypes();
Method requested = actualClass.getDeclaredMethod (methodName, parameterTypes);
return requested.invoke(duckLike, args);
}
};
final ClassLoader originalObjectClassLoader = duckLike.getClass().getClassLoader();
Duck woodenDuck = (Duck) Proxy.newProxyInstance(
originalObjectClassLoader,
new Class[] { Duck.class },
invocationHandler
);
return woodenDuck;
}
private interface Duck {
void quack();
};
public static void makeItQuack (Duck duck) {
duck.quack();
}
public static void main (String args[]) {
Object quacksLikeADuck = new Object() {
void quack() {
System.out.println ("Quack!");
}
};
// Does not compile -- makeItQuack(DuckDemo.Duck) [...] cannot be applied to (java.lang.Object)
// makeItQuack (quacksLikeADuck);
// Runtime java.lang.ClassCastException: [...] cannot be cast to GenericProxyFactory$Duck
// makeItQuack ((Duck)quacksLikeADuck);
Duck d = getDuckProxy(quacksLikeADuck);
makeItQuack (d);
}
}
価値のあることとして、IBM developerWorks には、動的プロキシーのトピックに関する優れた記事もあります。