В Clojure я использую gen-class
с библиотекой Java. Программист обычно предоставляет два класса, которые реализуют интерфейс и расширяют класс, соответственно. Предполагается, что оба класса относятся друг к другу, и это трудно избежать этой циклической зависимости, учитывая то, как библиотека была разработана.Как скомпилировать классы класса gen с циклическими типами подсказок?
Циклы не будут проблемой - компилятор не должен знать о них, за исключением того, что я пытаюсь оптимизировать код, разумно добавляя подсказки типов (с огромными ускорениями). Я смог избежать жалоб компилятора на циклические зависимости, реорганизовывая код, и я свел проблему до одного типа:
В одном исходном файле 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).
Это работает, потому что, когда Foo
компилируется во второй раз, Bar
существует, поэтому компилятор не жалуется.
Есть ли способ скомпилировать оба класса без удаления и добавления подсказки типа? (Или по-другому, что я должен думать об этой ситуации?)
Спасибо pete23. Икки, я попробую.Извините за абстрактное описание - пытаясь сохранить ненужные данные, а настоящие имена классов - «Студенты» и «Студенты», что сбивает с толку. Существует много 'Foo' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''/проекты/каменщик)). Каждый «Студент» должен иметь метод «step», который многократно вызывается методами планирования в суперклассе «Студенты». Возможно, возможно, что «Студент» расширяет класс планирования, но также и icky: несколько планировщиков, которые просто не вызываются. – Mars
pete23, либо компилятор запутался, либо я (вы можете догадаться, что более вероятно). Вернуться к foo/bar language: у Foo.clj теперь есть 'new-foo', как в вашем ответе. Bar.clj включает '(ns Foo) (объявить new-foo) (ns Bar)' before '(Foo/new-foo)' в определении функции, как это предлагается в ответе, который вы связали. 'Bar' указан первым в последовательности': aot' в project.clj. Он компилируется! Но во время выполнения он выдает «IllegalStateException: попытка вызывать несвязанные fn: # 'Foo/new-foo'. Whaat ?? Почему это несвязано? Я путаю компилятор с помощью переключателя пространства имен, я думаю. – Mars
Хммм, это говорит о том, что он не поднимает фу ... Повесить. – pete23