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 (работает, я пытался) или используя самоанализ (не пробовал).

Надеюсь это поможет

Другие вопросы по тегам