title: Scala name mangling of private fields and JavaFX FXML injection
body: <p>The following example and explanations are quite long, so here is the gist of my question: how to deal with scalac's name-mangling of private fields when using a framework which insists on performing field injection (on fields which really should stay private)?</p>
  
  <hr>
  
  <p>I am writing an application in Scala, using ScalaFX/JavaFX and FXML. When you use FXML to define your views in JavaFX, objects defined in FXML (such as buttons and text fields) are injected into the controller by :</p>
  
  <ul>
  <li>adding an <code>fx:id</code> property to the FXML elements</li>
  <li>adding (usually private) fields to the controller, with the <code>@FXML</code> annotation and with field names matching the values of the <code>fx:id</code> properties defined in the FXML</li>
  <li>when the <code>FXMLoader</code> instantiates the controller, it automatically injects the <code>fx:id</code> annotated elements into the matching <code>@FXML</code> annotated fields of the controller through reflexion</li>
  </ul>
  
  <p>I'm not a big fan of field injection, but that's how FXML works. However, I've run into unexpected complications in Scala, due to field name mangling performed by the compiler in some circumstances...</p>
  
  <p>Here is an example application :</p>
  
  <p>test/TestApp.scala (nothing interesting, just needed to run the example)</p>
  
  <pre><code>package test
  
  import javafx.application.Application
  import javafx.fxml.FXMLLoader
  import javafx.scene.{Scene, Parent}
  import javafx.stage.Stage
  
  object TestApp {
    def main(args: Array[String]) {
      Application.launch(classOf[TestApp], args: _*)
    }
  }
  
  class TestApp extends Application {
    override def start(primaryStage: Stage): Unit = {
      val root: Parent = FXMLLoader.load(getClass.getResource("/test.fxml"))
      val scene: Scene = new Scene(root, 200, 200)
  
      primaryStage.setTitle("Test")
      primaryStage.setScene(scene)
      primaryStage.show()
    }
  }
  </code></pre>
  
  <p>test.fxml (the view)</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  
  &lt;?import javafx.scene.control.*?&gt;
  &lt;?import java.lang.*?&gt;
  &lt;?import javafx.scene.layout.*?&gt;
  
  
  &lt;VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
        prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1"
        fx:controller="test.TestController"&gt;
      &lt;children&gt;
          &lt;CheckBox fx:id="testCheckBox" mnemonicParsing="false" text="CheckBox"/&gt;
          &lt;Button fx:id="testButton" mnemonicParsing="false" text="Button"/&gt;
      &lt;/children&gt;
  &lt;/VBox&gt;
  </code></pre>
  
  <p>test/TestController.scala (the controller for the test.fxml view)</p>
  
  <pre><code>package test
  
  import javafx.fxml.FXML
  import javafx.scene.{control =&gt; jfxsc}
  
  import scalafx.Includes._
  
  class TestController {
    @FXML private var testCheckBox: jfxsc.CheckBox = _
    @FXML private var testButton: jfxsc.Button = _
  
    def initialize(): Unit = {
      println(s"testCheckBox=$testCheckBox")
      println(s"testButton=$testButton")
  
      testCheckBox.selected.onChange {
        testButton.text = "changed"
      }
    }
  }
  </code></pre>
  
  <p>When running the application, the <code>println</code> statements show that <code>testCheckBox</code> gets injected properly, but <code>testButton</code> is null. If I click on the checkbox, there is, as expected, a <code>NullPointerException</code> when calling <code>testButton.text_=</code>.</p>
  
  <p>The reason is quite obvious when looking at the compiled classes :</p>
  
  <ul>
  <li>There is a <code>TestController$$anonfun$initialize$1</code> class, for the anonymous function passed to <code>testCheckBox.selected.onChange()</code> in the <code>initialize()</code> method</li>
  <li>In the <code>TestController</code> class, there are two private fields : <code>testCheckBox</code> (as expected) and <code>test$TestController$$testButton</code> (rather than just <code>testButton</code>), and the accessor/mutator methods. Of those, only the accessor method for <code>test$TestController$$testButton</code> is public.</li>
  </ul>
  
  <p>Clearly, the Scala compiler mangled the name of the <code>testButton</code> field because it had to make its accessor method public (to access it from <code>TestController$$anonfun$initialize$1</code>) and because the field and the accesor/mutator methods should keep the same name.</p>
  
  <hr>
  
  <p>Now, finally, here is my question: is there a reasonable solution to deal with this situation? Right now, what I have done is make the fields public: since the compiler doesn't need to change their visibility, it won't mangle their name. However, those fields really have no business being public.</p>
  
  <p>Note: Another solution would be to use the scala-fxml library, which completely hides the field injection, but I'd rather use bog-standard FXML loading for other reasons.</p>