簡體   English   中英

具有訪問者模式反射的Java泛型

[英]Java Generics with Reflection for Visitor Pattern

我想確保在我的代碼變得太大/太復雜而無法發布之前,它能夠正常工作。 我沒有足夠的方法來測試這是否符合我的預期

我正在做一些我想在AST上使用Visitor模式的事情。 我的目標是通過在超類中使用反射來消除在每個子類中覆蓋accept(Visitor)的需要,從而在實現新型TreeNode時使訪問者幾乎透明。

通過允許visit(TreeNode)它允許使用未知節點類型的默認方法,這樣,當添加新的節點類型時,無需更改舊訪客。

類Parameters R和P是訪問的返回值和參數,這是我在此編程棧交換問題上獲得的一個技巧。

為此,我需要執行以下操作:

public abstract class TreeNode {
    public final < R, P > R accept(TreeVisitor<R,P> v, P p){
        try{
            Method m = v.getClass().getMethod("visit", getClass(),Object.class);
            return (R)m.invoke(v, this,p);
        } catch (IllegalAccessException ex) {
        } catch (IllegalArgumentException ex) {
        } catch (InvocationTargetException ex) {
        } catch (NoSuchMethodException nsme){
        }
        return (R)v.visit(this,p);
    }
    public abstract void contains(TreeNode n);//and other methods
}
//in another file
interface TreeVisitor<R,P> {
    public R visit(TreeNode n,P p);//default
    public R visit(TreeNodeSubclass tns,P p);
    //all other subclasses as well
}
//from here lower is un-tested, written just now, just for this post, code
//somewhere else we have an algorithm to visit nodes
class DoStuff implements TreeVisitor<String,Void>{
     public String visit(TreeNode n, Void v){
          return n.toString();
     }
     public String visit(TreeNodeSubclass n, Void v){
         return "SUB:" + n.toString();
     }
}

//algorithm in a method somewhere
DoStuff ds = new DoStuff();
for(TreeNode node : inOrderTraverse(ROOT_NODE)){
     node.accept(ds);
}

是否可以按我期望的方式工作(假設inOrderTraverse(ROOT_NODE)正確生成了所有節點的列表)?

我的主要問題實際上是帶有getMethod調用的部分,因為類型擦除Object.class應該是正確的參數,盡管由於通用參數P人們更願意使用p.getClass() 但是,這將不起作用,因為類型擦除會導致Visitor中的實際方法簽名為Object visit(this.getClass(), Object)this.getClass()引用我正在使用的實際類的事實Node的子類,以在Visitor中獲得正確的重載方法。

我對此是否正確理解還是缺少某些東西?

我不確定如果將Object.class作為參數類型進行傳遞是否會起作用,但是我確實看到了另一個潛在的問題:如果新節點具有私有而不是公共的“訪問”方法,則應考慮例外,例如:

 try{ Method m = v.getClass().getMethod("visit", getClass(),Object.class); return (R)m.invoke(v, this,p); } catch (NoSuchMethodException e) { try { Method m = v.getClass().getDeclaredMethod("visit", getClass(),Object.class); return (R)m.invoke(v, this,p); } catch (Exception e){ return (R)v.visit(this,p);//default } } catch (Exception e){ return (R)v.visit(this,p);//default } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM