Clojure - как определить публичные изменяемые члены, используя deftype?
Я пытался запустить http://docs.oracle.com/javafx/2/get_started/fxml_tutorial.htm в clojure.
Я обнаружил, что, опуская @FXML
аннотация в версии Java и обнародование вещей, из:
public class FXMLExampleController {
@FXML private Text actiontarget;
@FXML protected void handleSubmitButtonAction(ActionEvent event) {
actiontarget.setText("Sign in button pressed");
}
}
чтобы:
public class FXMLExampleController {
public Text actiontarget;
public void handleSubmitButtonAction(ActionEvent event) {
actiontarget.setText("Sign in button pressed");
}
}
... что в принципе все еще работает, когда я нажимаю кнопку, и fxml может получить доступ к контроллеру public Text actiontarget
чей доступ обычно разрешен только через @FXML
аннотаций.
Поэтому я пытаюсь, чтобы у моего класса контроллера на основе clojure были открытые изменяемые поля, но в последние несколько часов поиска: gen-class и deftypes я не могу найти способ заставить его работать. Я смог получить доступ final
(по умолчанию) поля deftype из тестового кода Java, но единственное онлайн-обсуждение, которое я видел, говорит, что вы не можете иметь открытые и изменяемые поля, и попробовать: gen-class. Ну, я не могу найти это и в gen-class, и во всех примерах gen-class, которые мне удалось найти, используются поля класса только из clojure; Я не уверен, как определить: состояние в: gen-классе так, чтобы оно было доступно из Java, и я не знаю, как сделать их изменяемыми и общедоступными.
Моя следующая вещь - попробовать аннотации clojure, а затем использовать поле сценария fx: вместо fx:controller для определения обратного вызова clojure... но я хочу убедиться, что это выполнимо / невыполнимо с deftype или gen-class в первую очередь.
Так может кто-нибудь сказать мне, возможно ли сделать java-доступный класс с открытыми изменяемыми полями в clojure?
Благодарю.
2 ответа
Нет, вы не можете определять открытые изменяемые поля в Clojure. Это относится как к deftype
а также gen-class
,
Я полагаю, вы могли бы попытаться выяснить, будет ли JavaFX с удовольствием вызвать геттер и, если да, определить некоторые getFoo
методы в Clojure вместо.
Довольно поздно, как ответ, но если бы я нашел этот вопрос, другие люди могли бы также...:)
Я наткнулся на ту же самую проблему OP (то есть, я пытаюсь дублировать в сокрытии пример FXML в руководстве по javafx), и это мое решение:
1) Создайте интерфейс со всеми методами, необходимыми в моем FXML для взаимодействия, управляемого событиями (только один в моем случае, который отражает метод, определенный в контроллере в середине примера):
(definterface MyFXMLControllerMethods
(^void handleSubmitButtonAction (^javafx.event.ActionEvent event )))
2) затем используйте deftype
создать новый тип Java, реализующий интерфейс, и, что очень удобно, определить частное изменяемое поле с помощью @FXML
аннотация:
(deftype MyFXMLController [^{:volatile-mutable true javafx.fxml.FXML true} actiontarget]
MyFXMLControllerMethods
(^void handleSubmitButtonAction [this ^javafx.event.ActionEvent event]
(.setText actiontarget "Sign in button pressed!"))
Initializable
(^void initialize [this ^java.net.URL location ^java.util.ResourceBundle resources]
(assert (not= actiontarget nil)))) ; this test passes! =)
который, как правильно указал OP, является ключом, позволяющим загрузчику FXML получать доступ к закрытым полям контроллера посредством самоанализа.
Что действительно хорошо в этом подходе, так это то, что он не требует статической компиляции, поэтому, кроме Application class
все остальное может быть динамичным.
Другие решения могут включать инициализацию каждого поля вручную lookup
(работает, я пытался) или используя самоанализ (не пробовал).
Надеюсь это поможет