Как я называю перегруженные методы Java в Clojure

Для этого класса Java в качестве примера:

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

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

Когда я запускаю Clojure и пытаюсь назвать тест (интервал) метод, тест (Объект), метод называют вместо этого, потому что Clojure автоматически поля целое число в java.lang. Целочисленный объект.

Как я вынуждаю Clojure назвать тест (интервал) метод?

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

Я хочу назвать методы как Component.add(Component comp, int index) в AWT, но вместо этого продолжают звонить add(Component comp, Object constraints), таким образом, кнопки на моей панели инструментов всегда появляются в неправильном порядке.

15
задан Georg Fritzsche 27 April 2010 в 16:07
поделиться

2 ответа

На канале #clojure на Freenode только что идет обсуждение этой самой темы. Крис Хаузер (который собирался опубликовать ответ, но в конце концов решил, что он слишком занят, чтобы сделать это) опубликовал Gist , который демонстрирует, что происходит с логическим значением vs. Перегруженный метод объекта ; оказывается, что в некоторых сценариях в дополнение к приведению типа (boolean ...) требуется подсказка типа. Обсуждение было весьма поучительным, несколько темных уголков процесса компиляции Clojure стали хорошо освещены. (См. Ссылки на журнал IRC ниже.)

В основном, если объект создается прямо в форме вызова метода - (. Foo (Foo.) ...) , скажем, - то подсказка типа не требуется; это также не обязательно, если объект был сконструирован как значение для локального значения во включающей форме let (см. обновление 2 ниже и мою версию Gist). Однако, если объект получен с помощью поиска Var, требуется подсказка типа, которая может быть предоставлена ​​либо на самом Var, либо на месте вызова на символе, используемом для ссылки на Var.

Код Java из Gist:

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 , чтобы иметь возможность скомпилировать прямой вызов метода. В противном случае создается впечатление, что создается основанный на отражении код, который, по-видимому, упускает из виду тот факт, что аргумент должен быть примитивным на этом пути.

Мои дополнения следуют (а вот мой ответвитель вышеупомянутого 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"

Эта тема впервые была поднята на этом этапе .Чаузер разместил Gist через полчаса , и после этого обсуждение становилось все более и более интересным.

15
ответ дан 1 December 2019 в 03:13
поделиться
user=> (.test (foo.TestInterop.) 10)
"Test(Object)"
user=> (.test (foo.TestInterop.) (int 10))
"Test(int)"

Числа в Clojure обычно заключены в рамку (int => Integer), если вы специально не запрашиваете примитивы.

Здесь есть дополнительная информация о примитивах в Clojure.

8
ответ дан 1 December 2019 в 03:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: