为什么Clojure核心库使用具体派生?

10
Clojure类型机制的文档中,它指出:
  • 具体派生是不好的
    • 你无法从具体类导出数据类型,只能从接口导出
然而,一些核心Clojure类使用具体派生(还有其他例子,但这些是唯一一个超类属于clojure.lang的情况):
  • ARef扩展AReference
  • Agent扩展ARef
  • Atom扩展ARef
  • Namespace扩展AReference
  • Ref扩展ARef
  • Var扩展ARef
此外,有许多抽象类。然而,在Clojure中没有创建抽象类的等效方法,对我来说,扩展抽象类似乎具有与常规具体派生相同的缺点。
为什么在这里使用具体派生?

同一页面还警告不要改变性和封装性,然而 clojure.lang 中的类包含大量可变的私有字段。不要混淆语言的内部实现细节与其预期使用方式。 - Alex
1
@Alex 我之所以关心,是因为在Clojure中实现与clojure.core函数兼容的新数据结构的唯一方法是扩展clojure.lang接口。如果该包中的所有内容确实只是实现细节,那么不应需要了解其工作方式就能进行此类扩展。 - Sam Estep
1个回答

3

在哲学方面,我感觉自己不够权威,但是我会给出我的两分钱。

引用文本出现的原因是为了警告滥用defrecorddeftype。Clojure不鼓励将记录/类型公开为API。相反,尽可能应该公开接口。毕竟,OO语言公开类,FP语言公开函数/方法/接口。

另一方面,你提到Clojure的实现本身使用抽象类并继承它们。我更愿意考虑它们为“某些人必须做的肮脏工作”。JVM被设计为最高效地处理OO世界中的基元。OO世界虚拟机和FP世界语言之间的差距必须由某些人来填补。


这很有道理,但我需要看到更多支持你的论点的证据,才能相信在这里使用抽象类只是一种“必要的恶”,并且如果没有JVM的性能特征,它将劣于使用纯接口。看起来Rich Hickey在这里有一个非常明确的原因。 - Sam Estep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接