二重呼び出しを使用できます。それがより良い解決策であるという約束はありませんが、代替手段です。
コード例
import java.util.HashMap;
public class Example {
public static void main(String[] argv) {
Example ex = new Example();
ICacheable[] cacheableObjects = new ICacheable[]{new MyObject(), new OtherObject()};
for (ICacheable iCacheable : cacheableObjects) {
// depending on whether the object is a MyObject or an OtherObject,
// the .put(Example) method will double dispatch to either
// the put(MyObject) or put(OtherObject) method, below
iCacheable.put(ex);
}
System.out.println("myObjects: "+ex.myObjects.size());
System.out.println("otherObjects: "+ex.otherObjects.size());
}
private HashMap<String, MyObject> myObjects = new HashMap<String, MyObject>();
private HashMap<String, OtherObject> otherObjects = new HashMap<String, OtherObject>();
public Example() {
}
public void put(MyObject myObject) {
myObjects.put(myObject.getKey(), myObject);
}
public void put(OtherObject otherObject) {
otherObjects.put(otherObject.getKey(), otherObject);
}
}
interface ICacheable {
public String getKey();
public void put(Example ex);
}
class MyObject implements ICacheable {
public String getKey() {
return "MyObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
class OtherObject implements ICacheable {
public String getKey() {
return "OtherObject"+this.hashCode();
}
public void put(Example ex) {
ex.put(this);
}
}
ここでの考え方は、キャストや使用の代わりに、オブジェクトのオーバーロードされたメソッドに自分自身を渡すオブジェクトのメソッドをinstanceof
呼び出すということです。どのメソッドが呼び出されるかは、そのオブジェクトのタイプによって異なります。iCacheable
.put(...)
Example
Visitor パターンも参照してください。私のコード例は、ICacheable.put(...)
メソッドがまとまりがないためににおいがしますが、Visitor パターンで定義されたインターフェイスを使用すると、そのにおいを取り除くことができます。
クラスthis.put(iCacheable)
から電話できないのはなぜですか?Example
Java では、オーバーライドは常に実行時にバインドされますが、オーバーロードはもう少し複雑です。動的ディスパッチとは、メソッドの実装が実行時に選択されることを意味しますが、メソッドのシグネチャはコンパイル時に決定されます。(詳細については、Java 言語仕様の第 8.4.9 章を参照してください。また、本のJava Puzzlersの 137 ページにあるパズル「Making a Hash of It」も参照してください。)