(reify & opts+specs)
reify是一个宏,结构如下:
(reify options* specs*)
目前没有说明options,不需要指定。每个specs由协议或接口名及后跟的0个或多个方法体组成:
protocol-or-interface-or-Object
(methodName [args+] body)*
如果是协议或接口,需要提供所有的方法实现。如果是对象,还可以覆盖对象中的方法。需要说明的是,方法的第一个参数必须指定相应的目标对象,在Java语言中,就是“this”。
例子:
user=> (str (let [f "foo"]
#_=> (reify Object
#_=> (toString [this] f))))
"foo"
user=> (seq (let [f "foo"]
#_=> (reify clojure.lang.Seqable
#_=> (seq [this] (seq f)))))
(\f \o \o)
再来一个例子:
user=> (def server (reify
#_=> Server
#_=> (server-init [this]
#_=> (str "server init"))
#_=> (server-start [this]
#_=> (str "server start"))))
#'user/server
user=> (.server-init server)
"server init"
user=> (.server-start server)
"server start"
再来一个例子:
user=> (def def-fp (reify
#_=> Server
#_=> (server-init [this]
#_=> (str "server init"))
#_=> (server-start [this]
#_=> (str "server start"))
#_=> Client
#_=> (client-init [this]
#_=> (str "client init"))
#_=> (client-start [this]
#_=> (str "client start"))))
#'user/def-fp
user=> (class def-fp)
user$reify__1440
user=> (.server-init def-fp)
"server init"
user=> (.server-start def-fp)
"server start"
user=> (.client-init def-fp)
"client init"
user=> (.client-start def-fp)
"client start"
一个实际的例子:
<!--[if ppt]-->•<!--[endif]-->
<!--[if ppt]-->•<!--[endif]-->
defprotocol
core.clj:
;;;; (ns clojure.wf.core (import java.util.function.Function) (:gen-class)) ;;; control flow ;;; @see com.wf.core.AbstractControlFlow (defprotocol AbstractControlFlow ;; (getFunctionExpress [this]))
TestFunction.java
import java.util.function.Function;
public class TestFunction implements Function<String, String> {
public TestFunction() {
System.out.println("test function");
}
public String apply(String s) {
System.out.println(s);
return s;
}
}
(ns clojure.wf.test
(import java.util.function.Function)
(import com.wf.core.TestFunction)
(:require [clojure.test :refer :all]
[clojure.wf.core]))
;;;
(deftype AControlFlow [^Function functionExpress]
clojure.wf.core/AbstractControlFlow
(getFunctionExpress
[this]
functionExpress))
(deftest getFunctionExpressTest
(println "testing clojure.wf.core.AControlFlow/getFunctionExpress[_]")
(comment "
testing clojure.wf.core.AControlFlow/getFunctionExpress[_]
...
")
;
(def tfn (TestFunction.))
;
(def a (AControlFlow. tfn))
; call fn getFunctionExpress
(def functionExpress (.getFunctionExpress a))
; call fn apply
(def result (.apply functionExpress "what..."))
(println result))
>lein test :only clojure.wf.test/getFunctionExpressTest lein test clojure.wf.test testing clojure.wf.core.AControlFlow/getFunctionExpress[_] test function what... what... Ran 1 tests containing 0 assertions. 0 failures, 0 errors.
defprotocol 在定义方法的时候不能指定参数和返回类型。这在编译成java后全部映射为Object。
definterface
corex.clj
;;;; (ns clojure.wf.corex (import java.util.function.Function) (:gen-class)) (definterface AbstractControlFlow ;; function express (^java.util.function.Function getFunctionExpress []))
TestFunction.java
import java.util.function.Function;
public class TestFunction implements Function<String, String> {
public TestFunction() {
System.out.println("test function");
}
public String apply(String s) {
System.out.println(s);
return s;
}
}
corextest.clj
(ns clojure.wf.corextest
(import java.util.function.Function)
(import com.wf.core.TestFunction)
(:require [clojure.test :refer :all]
[clojure.wf.corex]))
;;;
(deftype AControlFlow [functionExpress]
clojure.wf.corex.AbstractControlFlow
(^Function getFunctionExpress
[this]
(println "fn getFunctionExpress called...")
functionExpress))
(deftest getFunctionExpressTest
(println "testing getFunctionExpress")
(comment "
testing getFunctionExpress
...
")
;
(def tfn (TestFunction.))
;
(def a (AControlFlow. tfn))
; call fn getFunctionExpress
(def functionExpress (.getFunctionExpress a))
; call fn apply
(def result (.apply functionExpress "what..."))
(println result))
>lein test :only clojure.wf.corextest/getFunctionExpressTest lein test clojure.wf.corextest testing getFunctionExpress test function fn getFunctionExpress called... what... what... Ran 1 tests containing 0 assertions. 0 failures, 0 errors.