Clojure代理是否总是调用super.method()?

问题描述:

使用Clojure proxies时,传递给代理的fns应该覆盖现有的方法还是与super.method()一起调用?Clojure代理是否总是调用super.method()?

在以下代码中,RequestHandler.get()与代理get []一起被调用。

;see: http://github.com/paulosuzart/JTornado 
(ns org.ctornadoweb) 
(import '(org.jtornadoweb Web$RequestHandler)) 
(import '(org.jtornadoweb HttpServer Web$Application)) 


(let [myHandler (proxy [Web$RequestHandler] [] 
        (get [] 
        (.write "Hi CLJ")) 
        (post [] 
        (.write "POST")))] 

(.listen 
    (HttpServer. 
    (.add (Web$Application.) "/" (class myHandler)) 
    false nil false) 8089)) 

同样的情况,在编译/继承版本:

; Starts a JTornado HTTP Server and a sample RequestHandler. 
; Bit verbose due to compilation directives. Recommendation is to generate 
; a set of macros to hide this. 
(ns org.ctornadoweb 
; Compiled and implements a static main method to start the server 
    (:import (org.jtornadoweb HttpServer) 
      (org.jtornadoweb.Web$Application) 
      (org.jtornadoweb.Web$RequestHandler)) 
    (:gen-class :prefix "server-")) 

(gen-class 
:name org.ctornadoweb.MyHandler 
:extends org.jtornadoweb.Web$RequestHandler 
:prefix "do") 

(defn do-get [this] 
    "Handles the HTTP GET method" 
    (.write "hello clojure")) 
(defn do-post [this] 
    "Handles the HTTP POST method" 
    (.write (.getArgument "name" "default" false))) 


(defn server-main [] 
    "main method" 
(.listen 
    (org.jtornadoweb.HttpServer. 
    (.add (org.jtornadoweb.Web$Application.) "/" org.ctornadoweb.MyHandler) 
    false nil false) 8089)) 

;use (compile 'org.ctornadoweb) 

跟踪显示代理获得被调用,然后super.get,抛出什么(默认)异常。

HTTP 405: Method Not Allowed 
    at org.jtornadoweb.Web$RequestHandler.get(Web.java:72) 
    at org.ctornadoweb.proxy$org.jtornadoweb.Web$RequestHandler$0.get(Unknown Source) 

我试图找到一些关于Clojure代理的实际行为的文字。有人可以提供这种帮助吗?

+2

我怀疑proxy'的'一些误用在你的身边。 'proxy'创建一个* anonymous *类。所以调用'class'是非常值得怀疑的。你应该在某处传递对象。如果你需要一个班级,你必须使用具有AOT编译功能的'gen-class'。 – kotarak 2010-07-19 07:07:19

+0

我错在哪里?请参阅http://gist.github.com/480886生成类仍会导致相同的super.method()行为。任何想法? – paulosuzart 2010-07-20 03:17:49

+1

您必须在前缀中指定连字符。 '(gen-class ...:prefix do- ...)'目前你的类没有看到实现,因此称为超类。 – kotarak 2010-07-20 21:42:18

不,超级方法不会自动调用,但您可以用proxy-super明确地调用它。

下面的测试情况表明事情的工作,因为他们应该:

user=> (def foo 
     (proxy [java.util.ArrayList] [] 
      (clear [] (println "not clearing")))) 
#'user/foo 
user=> (.size foo) 
0 
user=> (.add foo "hi") 
true 
user=> (.add foo "bye") 
true 
user=> (.size foo) 
2 
user=> (.clear foo) 
not clearing 
nil 
user=> (.size foo) 
2 

如果super.clear()都拿到叫,大小将显示为0。