使用defrecord与defprotocol的注意事项

简单地说,protocol是clojure中的接口,record是clojure中的数据类型。

可以通过这样的code定义一个protocol

(defprotoco DummyProtocol
  "doc string..."
  (method-one [self x] "doc string..."))

需要注意的是,protocol里所有方法的第一个参数都是self/this参数(类似python),从第二个开始才是调用时传入的参数。如果方法要重载呢?

(defprotocol DummyProtocol
  "doc string..."
  (method-one [self x] [self x y] "doc string")
)

Apress的 Practical Clojure 书里的例子,给重载的参数表加上了括号,这样会导致编译错误(注记)。

定义一个record实现protocol

(defrecord DummyRecord [a b c]
  DummyProtocol
  (method-one [self x] (+ a x))
  (method-one [self x y] (+ a x y)))

Practical Clojure里关于这部分的代码,又丢掉了self参数(注记)。

最后还有一个问题,如果直接use你的ns,你会发现调用record时出现:
java.lang.IllegalArgumentException: Unable to resolve classname: DummyRecord

怎么回事,不是都use了吗?原因是record被编译成了java对象,所以引用时要用java对象的引用方式,import之。