Clojure reify

 

reify
(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"
 
一个实际的例子:

Clojure reify
 
 
 
 
 
 
 
 
<!--[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.