В Clojure я использую gen-class
с библиотекой Java. Программист обычно предоставляет два класса, которые реализуют интерфейс и расширяют класс соответственно. Предполагается, что два класса ссылаются друг на друга, и трудно избежать этой циклической зависимости, учитывая способ проектирования библиотеки.
Циклы не будут проблемой — компилятору не нужно знать о них — за исключением того, что я пытаюсь оптимизировать код, разумно добавляя подсказки типов (с огромным ускорением). Мне удалось избежать жалоб компилятора на циклические зависимости, реорганизовав код, и я свел проблему к подсказке одного типа:
В одном исходном файле Foo.clj у меня есть эта функция/метод, который требуется интерфейсом, который реализует класс:
(defn -step
[^Foo this ^Bar bar]
...)
Другой исходный файл, Bar.clj, создает коллекцию экземпляров Foo, поэтому мне приходится ссылаться на класс Foo. В моем Leiningen project.clj у меня есть такая строка:
:aot [Foo Bar]
Я не получаю ошибку циклической зависимости. Вместо этого я получаю ClassNotFoundException
: если я поставлю Foo
первым после :aot
, компилятор жалуется, что он не знает о Bar
при компиляции Foo
из-за подсказки типа ^Bar
в -step
. Если я поставлю Bar
первым после :aot
, компилятор не сможет найти Foo
при компиляции Bar
из-за вызовов (Foo.)
в Bar.clj.
Мое текущее решение таково:
- Удалите подсказку типа
^Bar
в определении-step
в Foo.clj. - Скомпилируйте оба класса.
- Добавьте подсказку типа обратно в
-step
в Foo.clj. - Скомпилируйте
Foo
(т.е. снова запустите lein compile).
Это работает, потому что когда Foo
компилируется во второй раз, Bar
существует, поэтому компилятор не жалуется.
Есть ли способ скомпилировать оба класса без удаления и добавления подсказки типа? (Или по-другому, что я должен думать об этой ситуации?)