gpt4 book ai didi

java - 如何在 Clojure 中调用重载的 Java 方法

转载 作者:太空狗 更新时间:2023-10-29 22:53:29 24 4
gpt4 key购买 nike

对于此示例 Java 类:

package foo;
public class TestInterop
{ public String test(int i)
{ return "Test(int)"; }

public String test(Object i)
{ return "Test(Object)"; }
}

当我启动 Clojure 并尝试调用 test(int) 方法时,却调用了 test(Object) 方法,因为 Clojure 会自动将整数装箱到 java.lang.Integer 对象中。

如何强制 Clojure 调用 test(int) 方法?

user=> (.test (new foo.TestInterop) 10)
"Test(Object)"

我想在 AWT 中调用类似 Component.add(Component comp, int index) 的方法,但是继续调用 add(Component comp, Object constraints),所以我工具栏上的按钮总是以错误的顺序出现。

最佳答案

刚刚在 Freenode 上的#clojure channel 中就这个主题进行了讨论。 Chris Houser(他本来打算发布一个答案,但最终决定他太忙了没时间)发布了a Gist它演示了 booleanObject 重载方法会发生什么;事实证明,在某些情况下,除了 (boolean ...) 转换之外,还需要类型提示。讨论非常有启发性,Clojure 编译过程中的一些阴暗角落得到了很好的阐明。 (请参阅下面的 IRC 日志链接。)

基本上,如果一个对象是在方法调用形式中创建的——(.foo (Foo.) ...),那么类型提示是不必要的;如果对象已被构造为封闭 let 形式的本地值,则同样没有必要(请参阅下面的更新 2 和我的 Gist 版本)。但是,如果对象是通过 Var 查找获得的,则需要类型提示——可以在 Var 本身上提供,也可以在调用站点上用于引用 Var 的符号上提供。

Gist 中的 Java 代码:

package mypkg;

public class Ugly {
public Ugly(){}
public String foo(boolean i) { return "bool: " + i; }
public String foo(Object o) { return "obj: " + o; }
}

Clojure 代码:

(.foo (mypkg.Ugly.) 5)
;=> "obj: 5"

(.foo (mypkg.Ugly.) true)
;=> "obj: true"

(.foo (mypkg.Ugly.) (boolean true))
;=> "bool: true"


(def u (mypkg.Ugly.))
(.foo u (boolean true))
;=> "obj: true"

(.foo #^mypkg.Ugly u (boolean true))
;=> "bool: true"

请注意 Clojure 编译器如何需要 u 上的类型提示才能编译直接方法调用。否则,似乎会生成基于反射的代码,这显然忽略了参数在整个过程中是原语这一事实。

我的补充如下(这里是 my fork of the above Gist )。

;; renamed mypkg.Ugly to foo.TestInterop2 when doing my tests
user> (let [t (foo.TestInterop2.)]
(.foo t (boolean true)))
"bool: true"

;;; type-hinting the Var
user> (def #^foo.TestInterop2 x (foo.TestInterop2.))
#'user/x
user> (.foo x (boolean true))
"bool: true"

话题首次被提出at this point . Chuser 发布了 Gist half an hour later , 之后讨论变得越来越有趣。

关于java - 如何在 Clojure 中调用重载的 Java 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2722856/

24 4 0
文章推荐: c# - 工作线程上的 MessageBox
文章推荐: c++ - 在同一个盒子上的两个以太网接口(interface)之间发送数据
文章推荐: c# - 当对象具有集合属性时投影 IQueryable 时 Automapper 失败