为什么Clojure有五种方法来定义一个类而不是一个类?
Clojure具有gen-class,reify,proxy,deftype和defrecord来定义新类types的数据types。 对于语法简单并且不必要的复杂的语言来说,这似乎是一种失常。 有人能解释为什么是这样吗? Common Lisp风格的defclass能够吗?
这是三个不同因素的混合:
- jvm的特定types系统
- 定义types时,需要针对不同用例略有不同的语义
- 事实上,其中一些是随着语言的发展而发展起来的。
首先,我们来看看这些做什么。 deftype和gen-class是相似的,它们都为提前编译定义了一个命名类。 Gen-class是第一个,接下来是clojure中的deftype 1.2。 Deftype是优选的,并且具有更好的性能特征,但是更具限制性。 deftype类可以符合一个接口,但不能从另一个类inheritance。
Reify和Proxy都用于在运行时dynamic创build一个匿名类的实例。 代理来了第一,在clojure 1.2 reify与deftype和defrecord一起来了。 Reify是优选的,就像deftype一样,语义不是太严格。
这就产生了这样的问题:既然它们同时出现,并且具有类似的作用,那么为什么既定型又定义了折旧。 对于大多数目的,我们将要使用defrecord:它具有我们所知道和喜爱的所有各种clojure善良,sequability等等。 Deftype旨在用作实现其他数据结构的低级构build块。 它不包括常规的clojure接口,但它有可变字段的选项(虽然这不是默认的)。
为进一步阅读检查:
clojure.org数据types页面
引入了deftype和reify的google组线程
简短的回答是,他们都有不同的和有用的目的。 复杂性是由于需要与底层JVM的不同function进行有效的互操作。
如果你不需要任何Java互操作,那么99%的时间你最好坚持defrecord或简单的Clojure地图。
- 如果你想使用协议,使用defrecord
- 否则,一个普通的Clojure地图可能是最简单也是最容易理解的
如果您的需求更复杂,那么下面的stream程图就是解释为什么您会select其中一个选项的一个很好的工具:
http://cemerick.com/2011/07/05/flowchart-for-choosing-the-right-clojure-type-definition-form/