Clojure:如何从长代理语句中分解代理方法代码?

时间:2011-10-26 23:01:54

标签: clojure proxy refactoring

我有一个Clojure proxy语句变得庞大而混乱,所以我决定尝试将beginDrag方法重新定义的代码从proxy语句中分解出来,如下所示:

(defn enhanced-start-drag
  ""
  [pie]
  (let [pobj   (. pie getPickedNode)
    pobj-coll (seq (.. pie getInputManager
               getKeyboardFocus getSelection))]
    (println pobj)
    (println pobj-coll)
    (println "----------")
    (proxy-super startDrag pie)))  ; THIS IS LINE 94 (SEE ERROR MSG)



(defn custom-selection-event-handler [marqueeParent selectableParent]
  (proxy [PSelectionEventHandler]  [marqueeParent selectableParent]
    (decorateSelectedNode [node]
              (let [stroke-color (Color/red)]
                (.setStrokePaint node stroke-color)))
    (undecorateSelectedNode [node]
                (let [stroke-color (Color/black)]
                  (.setStrokePaint node stroke-color)))
    (startDrag [pie]    ; pie is a PInputEvent
           (enhanced-start-drag pie))
    (endStandardSelection [pie]     ; pie is a PInputEvent
              (let [pobj   (.getPickedNode pie)
                slip   (. pobj getAttribute "slip")
                ]
                (swap! *last-slip-clicked*
                   (fn [x] slip))))))

我收到以下编译错误:

cd /Users/gw/tech/clojurestuff/cljprojects/infwb/src/infwb/
1 compiler notes:

Unknown location:
  error: java.lang.Exception: Unable to resolve symbol: this in this context

core.clj:94:5:
  error: java.lang.Exception: Unable to resolve symbol: this in this context 
    (core.clj:94)

Compilation failed.

只要将enhanced-start-drag的正文恢复到proxy语句的正文中,一切正常。

我的问题:有没有办法将杂乱的细节移到单独的函数中以提高代码的可读性?

感谢您的所有想法和解决方案。


更新,10/27/11:请参阅以下评论。 Arthur Ulfeldt尖锐地指出该问题是捕获的引用,Dave Ray也说得对,你所要做的就是将this作为参数添加到enhanced-start-drag然后{{1}将正常工作。当我进行以下两项更改(对proxy-super正文没有任何更改)时,我的代码再次运行:

enhanced-start-drag

  (defn enhanced-start-drag
    ""
    [pie this]

BTW,我的项目使用Dave Ray的 (startDrag [pie] ; IN THE PROXY STMT IN custom-selection-event-handler (enhanced-start-drag pie this)) 项目来获取Java Swing UI。 seesaw非常棒,其文档字符串和示例代码(比大多数商业软件要好得多)都很棒。我强烈推荐它!谢谢你,戴夫!

1 个答案:

答案 0 :(得分:4)

你被 symbol capture 咬了。在这种情况下,它是intentaional虽然你需要留意它。来自proxy-super

的文档
Use to call a superclass method in the body of a proxy method. 
Note, expansion captures 'this`

代理正在创建一个调用函数的类,当调用进入enhanced-start-drag时,this的值不是代理超级预期的值

您可能需要将this作为另一个参数传递给enhanced-start-drag,然后调用(. saved-this ...)而不是使用proxy-super。