Java 有没有办法在clojure中实现真正的私有功能?

Java 有没有办法在clojure中实现真正的私有功能?,java,clojure,Java,Clojure,如前所述,私有clojure函数不是真正私有的,只是隐藏的。我不喜欢这个。在java中,标记为private的函数不能在类外调用,否则会引发编译错误。有没有办法确保我声明为私有的方法确实是私有的,因为没有其他人可以调用它们?有没有办法至少模拟一下这一点?为了让我们的术语更清楚,Java8有Java.util.function.function,但我认为您实际上指的是Java方法。Clojure函数实现Clojure.lang.IFn接口的类不是方法,而是类。IFn扩展了可运行和可调用接口 严格地

如前所述,私有clojure函数不是真正私有的,只是隐藏的。我不喜欢这个。在java中,标记为private的函数不能在类外调用,否则会引发编译错误。有没有办法确保我声明为私有的方法确实是私有的,因为没有其他人可以调用它们?有没有办法至少模拟一下这一点?

为了让我们的术语更清楚,Java8有Java.util.function.function,但我认为您实际上指的是Java方法。Clojure函数实现Clojure.lang.IFn接口的类不是方法,而是类。IFn扩展了可运行和可调用接口

严格地说,通过实现词法闭包,实际上可以将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中,当我们想要进行防御性编码时,我们更倾向于使用不可变的数据类型,以确保无知或恶意的编码器不会导致无效状态,因为我们不依赖状态的变异来实现我们的算法。

为了让我们的术语更清楚,Java 8有Java.util.function.function,但我认为你实际上指的是java方法。Clojure函数实现Clojure.lang.IFn接口的类不是方法,而是类。IFn扩展了可运行和可调用接口

严格地说,通过实现词法闭包,实际上可以将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中,当我们想进行防御性编码时,我们更喜欢依靠不可变的数据类型,确保无知或恶意的编码者不会导致无效状态,因为我们不依赖状态的变异来实现我们的算法。

问题很简单,让对象的私有元素成为私有元素的JVM方法就是把它变成私有属性。即使在Java中,您也可以很容易地从外部调用私有函数,但只有编译器妨碍您直接调用私有函数。间接地,您可以获取类的函数并调用它

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

另外,私有属性作为元数据存储在符号中。但是我们处理的是值,这里没有更多的元数据


但很有可能你仍然太过拘泥于OO的观点

问题很简单,使对象的私有元素成为私有元素的JVM方法就是将其设置为私有属性。即使在Java中,您也可以很容易地从外部调用私有函数,但只有编译器妨碍您直接调用私有函数。间接地,您可以获取类的函数并调用它

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

另外,私有属性作为元数据存储在符号中。但我们处理智慧 h值,这里没有更多的元数据


但很有可能你仍然太过拘泥于OO的观点

我认为您只需检查调用方的名称空间,如果名称空间不是函数所在的名称空间,则会失败,但似乎会对该方法造成影响。在java中,标记为private的函数不能在类外调用;抛出一个错误。严格来说,这不是真的-直接引用它会导致编译错误,但可以在运行时通过reflection访问它。此外,需要显式引用var与运行时反射类似。当直接引用var时,您告诉运行时在ns中查找var的名称,通过反射,您告诉运行时在对象中查找方法的名称,可能会认为当前行为已经等同于java行为,只是在语法上更加简洁。您需要私有函数,以便可以控制状态变化。Clojure完全是关于不变性的,因此在语言中没有针对私有函数的内置方式。或者你只是不希望人们使用你可以随时更改的方法,而宁愿只公开那些可能形成未来稳定API的方法。这是松耦合,是一个很好的设计。这就是为什么许多纯函数式语言都提供了这种不涉及抽象的特性,比如racket的提供语法。我认为您只需检查调用方的名称空间,如果名称空间不是函数所在的名称空间,则会失败,但似乎会对该方法造成影响。在java中,标记为private的函数不能在类外调用;抛出一个错误。严格来说,这不是真的-直接引用它会导致编译错误,但可以在运行时通过reflection访问它。此外,需要显式引用var与运行时反射类似。当直接引用var时,您告诉运行时在ns中查找var的名称,通过反射,您告诉运行时在对象中查找方法的名称,可能会认为当前行为已经等同于java行为,只是在语法上更加简洁。您需要私有函数,以便可以控制状态变化。Clojure完全是关于不变性的,因此在语言中没有针对私有函数的内置方式。或者你只是不希望人们使用你可以随时更改的方法,而宁愿只公开那些可能形成未来稳定API的方法。这是松耦合,是一个很好的设计。这就是为什么许多纯函数式语言都提供了这种不涉及抽象的特性,比如racket的提供语法。