generics和访客模式
我对访问者模式和generics有问题。 我有一些抽象的class级,他们的孩子将被访问。 看看这段代码:
public abstract class Element extends SomeSuperClass { public void accept(Visitor v) { v.visit(this); } } public interface Visitor { void visit(T element); }
所以我的想法是:我有一些类层次结构(例如, Element
是SomeSuperClass
的子类)。 我有一些通用的Visitor
界面来访问这个层次结构。 现在在这个层次结构的中间是Element
类,它是抽象的并且拥有它自己的子类。
现在我希望Element
接受其子类的所有访问者,这就是我放这行的原因:
public void accept(Visitor v)
但现在我收到错误:
方法访问(
capture#1-of ? extends Element
)类型为Visitor
Visitor
不适用于参数(Element
)。
我明白了? extends Element
? extends Element
不是Element
。 我的问题是:我可以用不同的方式表达我的想法吗? 或者我在这种情况下错过了generics的想法?
请注意,
中的
可以是与Element
完全无关的类型,并且编译器必须确保visit(T t)
对每个可能的T
。
您调用的代码为Visitor.visit(Element e)
,但相关访问者可能是Visitor
。 这没有意义。
我认为“ Element
必须接受其子类的所有访问者”的要求没有意义:访问者必须至少能够访问Element
及其所有子类 。 那将是一个Visitor
。
构造accept(Visitor extends Element> v)
意味着v
可以是T extends Element
任何此类Visitor
。 这并不意味着访客本身将属于Visitor extends Element>
Visitor extends Element>
。 实际上,Java中甚至不存在这样的东西。 每个访问者都将具有与之关联的特定类型参数,而不是通配符。
那不行 – 参观者? extends Element
? extends Element
可能需要能够访问Element
没有或不知道的数据(属性/方法,…)。
你不能得到一个访问者,它应该访问扩展Element
对象,以便必须能够访问一个直接Element
或者另一个完全独立的Element
子类。
我认为你想要做的事情没有多大意义。 使Visitor
generics是无用的: 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
接口必须知道Element
层次结构中需要自定义visit()
实现的所有类。
编写它的最常用方法是:
public void accept(Visitor super Element> v) { v.visit(this); }
这样,即使是一个Visitor
也可以工作(为什么不应该这样)。
记住PECS(生产商extends
,消费者super
)。 访客是消费者,所以它应该是super
。