有没有办法在clojure中拥有真正的私人功能?

时间:2014-08-15 22:59:36

标签: java clojure

正如here所述,私有的clojure函数并不是真正的私有,只是隐藏。我不喜欢这个。在java中,标记为private 的函数不能在类外部调用,而不会抛出编译错误。有没有办法确保我声称为私有的方法私有的,没有其他人可以调用它们?有没有办法至少模拟这个?

2 个答案:

答案 0 :(得分:7)

为了使我们的术语直截了当,Java 8有java.util.function.Function,但我认为你实际上是指java 方法。 Clojure函数(实现clojure.lang.IFn接口的类)不是方法,而是类。 IFn扩展了RunnableCallable接口。

严格来说,实际上你可以通过实现词法闭包来隐藏Clojure函数,这样就没有可以暴露它的可访问的对象。

例如:

(ns my.hidden)

(fn not-here
   [x]
   (println "this can never be called"))

没有代码可以调用此函数。这个函数是如此隐藏,垃圾收集器可能会在创建它后立即将其从vm中删除。当然这没有用。

一个更现实的例子(但你可能不应该这样做):

(ns my.discreet)

(letfn [(a [x] (println "a with" x))
        (b [x] (println "b with" x))]
   (defn foo [x]
      (if (> (rand) 0.5)
             (a x)
            (b x))))

此处,来电者无法直接访问a或b。通过反射可以实现,但只能利用Clojure版本的已知实现细节。没有API,因此任何解决方案都将依赖于实现。引用一位Clojure开发人员的话说:“如果我这样做的话就会滥用实现细节,我会觉得不舒服。”

但重要的是隐藏这些功能实际上并不是做Clojure的惯用方法。在Clojure中,当我们想要进行防御性编码时,我们更倾向于依靠不可变数据类型来确保无知或恶意编码器不会导致无效状态,因为我们不依赖于状态变异来实现我们的算法。

答案 1 :(得分:0)

简单地说,JVM创建对象的私有元素的方法就是将属性设置为私有。即使在Java中,您也可以从外部轻松调用私有函数,只有那些阻碍您直接执行此操作的编译器。间接地你可以获得类的功能并调用它。

在Clojure中,对动态类型对象进行调用,隐私是键入的一部分。 惯用隐私仅对命名空间对象隐藏有用,并且由编译器很好地管理。内部状态私有变量没有实际意义,因为目标是最小化它们或更好地抑制它们。

另一方面,私有属性作为元数据存储在符号中。但是我们处理价值观,而且这里没有更多的元数据......

但从OO的角度来看,你可能仍然太过分了;)