3

Visitor パターンとジェネリックに問題があります。私は、子供たちが訪問される抽象クラスをいくつか持っています。このコードを見てください:

public abstract class Element extends SomeSuperClass {
    public void accept(Visitor<? extends Element> v) {
        v.visit(this);
    }
}

public interface Visitor<T extends SomeSuperClass> {
    void visit(T element);
}

つまり、アイデアは次のとおりです。クラス階層があります(たとえばElement、のサブクラスですSomeSuperClass)。Visitorこの階層にアクセスするための一般的なインターフェイスがいくつかあります。この階層の中間にElementクラスがあり、これは抽象的で独自のサブクラスを持っています。

Elementここで、そのサブクラスのすべての訪問者を受け入れたいので、次の行を追加します。

public void accept(Visitor<? extends Element> v)

しかし、今私はエラーを受け取っています:

capture#1-of ? extends Elementタイプのメソッド visit ( ) はVisitor<capture#1-of ? extends Element>、引数 ( ) には適用されませんElement

? extends Elementではないことは理解していElementます。私の質問は、私の考えを別の方法で表現できますか? または、この場合、ジェネリックのアイデアを見逃しただけですか?

4

4 に答える 4

3

あなたがやろうとしていることはあまり意味がないと思います。ジェネリックVisitorにするのは無意味です。accept()メソッドは、特定のビジター インターフェイスを引数として取り、 のサブクラスが のElement特定のオーバーロードを呼び出せるようにする必要がありvisit()ます。

interface Visitor {
  void visit(Element e);
  void visit(SubElement e);
}

class Element {
  public void accept(Visitor v) {
    v.visit(this);
  }
}

class SubElement { 
  public void accept(Visitor v) {
    v.visit(this);
  }
}

class ElementVisitor implements Visitor {
  public void visit(Element e) {}
  public void visit(SubElement e) {}
}

インターフェイスは、カスタム実装を必要とVisitorする階層内のすべてのクラスを認識している必要があることに注意してください。Elementvisit()

于 2012-08-24T13:28:39.253 に答える
3

それはうまくいきません - の訪問者は、持っていない、または知らない? extends Elementデータ (属性/メソッドなど) にアクセスできる必要があるかもしれません。Element

Elementオブジェクトを訪問することになっているElementビジターを取得することはできませんElement.

于 2012-08-24T12:51:52.097 に答える
2

inは完全に無関係な型である可能性がTあり、コンパイラは可能なすべての.<T extends SomeSuperClass>Elementvisit(T t)T

あなたが持っているコードは を呼び出しますがVisitor.visit(Element e)、問題の訪問者はVisitor<SubElement>. それは意味がありません。

「そのサブクラスのすべてのビジターを受け入れなければならない」という要件Elementは意味がないと思います。ビジターは少なくともElement すべてのサブクラスを訪問できる必要があります。それはVisitor<Element>.

コンストラクトは、がそのようなものになるaccept(Visitor<? extends Element> v)ことを意味します。ビジター自体が というタイプになるわけではありません。実際、そのようなものは Java にも存在しません。すべての訪問者には、ワイルドカードではなく、特定の型パラメーターが関連付けられています。vVisitor<T>T extends ElementVisitor<? extends Element>

于 2012-08-24T12:55:32.047 に答える
2

最も一般的な書き方は次のようになります。

public void accept(Visitor<? super Element> v) {
    v.visit(this);
}

そうすれば、 a でさえ機能しVisitor<Object>ます(なぜそうすべきではないのですか)。

PECS (生産者extends、消費者super) を思い出してください。訪問者は消費者であるため、 である必要がありますsuper

于 2012-08-24T19:57:48.860 に答える