問題を抽象的に定式化することから始めましょう。2 つのパブリック インターフェイス タイプがあります。それらの 1 つには、他のインターフェイス タイプのインスタンスを少なくとも 2 つ受け取るメソッドが含まれています。メソッドの実装は、渡されたオブジェクトの実装に依存します。
2 つのインターフェイスで構成される次のパブリック API について考えてみましょう。
public interface Node {
}
public interface Tree {
void connect(Node parent, Node child);
}
次に、その API を次のように実装します。
public class NodeImpl implements Node {
private final Wrapped wrapped;
public NodeImpl(Wrapped wrapped) {
this.wrapped = wrapped;
}
public Wrapped getWrapped() {
return wrapped;
}
}
public class TreeImpl implements Tree {
@Override
public void connect(Node parent, Node child) {
// connect parent and child using the wrapped object
}
}
public class Wrapped {
// wrapped object which actually represents the node internally
}
メソッド内のラップされたオブジェクトにアクセスする必要がありますが、メソッドは API の一部ではないconnectため、これは不可能です。getWrapped実装の詳細です。
connect問題は、実装の詳細を API に漏らさずにメソッドを実装するにはどうすればよいかということです。
これが私がこれまでに試したことです:
connectメソッドをNodeインターフェースに入れ、 を呼び出しますparent.connect(child)。これにより、親のラップされたオブジェクトにアクセスできるようになりますが、子のラップされたオブジェクトはまだ利用できません。渡された
Nodeのが型であると仮定してNodeImpl、ダウンキャストを使用してください。これは私には間違っているようです。他のNode実装があるかもしれません。ラップされたオブジェクトをノードに配置しないでください。をオブジェクトに
TreeImplマップするマップを使用してください。NodeWrappedこれは基本的に上記と同じです。インスタンスが関連付けられたマッピングを持たないメソッドにNode渡されるとすぐに壊れます。connect
Nodeインターフェイスにはメソッドが含まれる場合があることに注意してください。ただし、これはこの質問にとって重要ではありません。
また、インターフェースの宣言と実装の両方を管理していることに注意してください。
これを解決する別の試みは、メソッドをインターフェイスのメソッドに変換し、インターフェイスを汎用にすることconnectです。addChildNodeNode
public interface Node<T extends Node<T>> {
void addChild(Node<T> child);
}
public class NodeImpl implements Node<NodeImpl> {
private final Wrapped wrapped;
public NodeImpl(Wrapped wrapped) {
this.wrapped = wrapped;
}
public Wrapped getWrapped() {
return wrapped;
}
@Override
public void addChild(Node<NodeImpl> child) {
}
}
public class Wrapped {
// wrapped object which actually represents the node internally
}
public Node<NodeImpl> createNode() {
return new NodeImpl(new Wrapped());
}
private void run() {
Node<NodeImpl> parent = createNode();
Node<NodeImpl> child = createNode();
parent.addChild(child);
}
NodecreateNodeパブリック API の一部です。NodeImplそしてWrapped隠す必要があります。runクライアントコードです。ご覧のとおり、NodeImplはクライアントに表示される必要があるため、これはまだ漏れのある抽象化です。