【问题标题】:Does a Clojure proxy always invoke super.method()?Clojure 代理是否总是调用 super.method()?
【发布时间】:2023-03-21 00:54:01
【问题描述】:

在使用Clojure proxies 时,传递给代理的fns 应该覆盖现有方法,还是与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)

跟踪显示代理 get 被调用,然后是 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 代理的实际行为的词。有人可以帮忙吗?

【问题讨论】:

  • 我怀疑您对 proxy 的滥用。 proxy 创建一个 anonymous 类。所以打电话给class 是非常可疑的。您应该将对象本身传递到某个地方。如果你需要一个类,你必须使用 gen-class 和 AOT 编译。
  • 我哪里漏掉了重点?请参阅gist.github.com/480886 生成类仍然会导致相同的 super.method() 行为。有什么想法吗?
  • 您必须在前缀中指定连字符。 (gen-class ... :prefix do- ...) 目前你的类没有看到实现,因此调用了超级类。

标签: functional-programming clojure dynamic-languages


【解决方案1】:

不,super 方法不会被自动调用,但您可以使用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。

【讨论】:

    猜你喜欢
    • 2014-12-24
    • 1970-01-01
    • 2013-06-18
    • 2011-05-04
    • 2010-10-29
    • 2013-11-22
    • 1970-01-01
    • 2020-10-05
    • 2014-02-10
    相关资源
    最近更新 更多