我有一个有趣的情况,我想知道是否有更好的方法来做到这一点.情况是这样的,我有一个树结构(具体是抽象语法树),一些节点可以包含各种类型的子节点,但都从给定的基类扩展.
我想经常在这个树上做查询,我想找回我感兴趣的特定子类型.所以我创建了一个谓词类,然后我可以将其传递给通用查询方法.起初我有一个看起来像这样的查询方法:
public <T extends Element> List<T> findAll(IElementPredicate pred, Class<T> c);
其中Class参数仅用于指示返回类型.令我困扰的是这种方法是我的所有谓词都已经用于特定类型,所以这里有冗余信息.典型的呼叫可能如下所示:
List<Declaration> decls = 
    scope.findAll(new DeclarationPredicate(), Declaration.class);
所以我像这样重构它:
public <T extends Element> List<T> findAll(IElementPredicate<T> pred);
凡IElementPredicate界面看起来是这样的:
public interface IElementPredicate<T extends Element> {
    public boolean match(T e);
    public String getDescription();
    public Class<T> getGenericClass();
}
这里的要点是谓词接口被扩展以提供Class对象.它使得编写实际的findAll方法更加有效,并且它在编写谓词时增加了一些工作,但这些都是微小的"一次性"事情,它使查询调用更好,因为你没有添加额外的(可能是多余的)参数,例如
List<Declaration> decls = scope.findAll(new DeclarationPredicate());
我之前没有注意到这种模式.这是处理Java泛型语义的典型方法吗?只是好奇我是否错过了一些更好的模式.
Commments?
更新:
一个问题是你需要什么类?这是findAll的实现:
public <T extends Element> List<T> findAll(IElementPredicate<T> pred) {
    List<T> ret = new LinkedList<T>();
    Class<T> c = pred.getGenericClass();
    for(Element e: elements) {
        if (!c.isInstance(e)) continue;
        T obj = c.cast(e);
        if (pred.match(obj)) {
            ret.add(c.cast(e));
        }
    }
    return ret;
}
虽然匹配只需要一个T,但我需要确保该对象是一个T才能调用它.为此,我需要Class的"isInstance"和"cast"方法(据我所知).
| 归档时间: | 
 | 
| 查看次数: | 1296 次 | 
| 最近记录: |