Nachdem ich schon mehrfach Details zum Umstieg von älterem Code in JavaFX Script gepostet habe, folgt hier nochmal ein vollständiger Umstiegsanleitung für JavaFX Script auf die Finalversion 1.0.
Mein Buch zu JavaFX
Meine DVD mit dem Onlinetraining zu JavaFX.
Wer bereits mit JavaFX Script auf Basis erster Preversionen seit etwa Mitte 2007 programmiert hat, wird in der nun Ende 2008 erschienenen Finalversion 1.0 mit einigen Änderungen bzw. Umstrukturierungen konfrontiert.
Aber die Änderungen sind eigentlich gar nicht so wild. Insbesondere gibt es einen guten JavaFX Script™ Programming Language Migration Guide unter https://openjfx.dev.java.net/migration.html, auf dem auch diese Umstiegsanleitung in einigen Punkten basiert.
Insgesamt ist m.E. die Finalversion von JavaFX Script stringenter und logischer geworden und orientiert sich doch verstärkter an dem streng objektorientierten Konzept von Java selbst.
Operationen
In den Preversionen von JavaFX Script hat Sun mit Prozeduren experimentiert. Schon Funktionen sind in der streng objektorientierten Welt von Java gewagt, aber Prozeduren, die sogar einen Rückgabewert liefern konnten, waren wohl doch des Guten zu viel. In der Finalversion entfallen diese Prozeduren, die bisher mit dem Schlüsselwort operation eingeleitet wurden. Stattdessen werden grundsätzlich Funktionen verwendet, die mit dem Schlüsselwort function eingeleitet werden.
Beispiel alt:
class MeineKlasse {
function times2(x) { return x * 2; }
operation print(s) { System.out.println(s); }
}
Beispiel neu:
class MeineKlasse {
function times2(x) { return x * 2; }
function print(s) { System.out.println(s); }
}
Attributinitialisierung
Die Initialisierung von Attributen erfolgte bisher außerhalb einer Klassendefinition. Diese Technik wurde nun Java angeglichen und die Attribute werden bei der Deklarierung in der Klasse selbst initialisiert.
Beispiel alt:
class MeineKlasse {
attribute bar: Boolean; }
attribute Foo.bar = true;
Beispiel neu:
class MeineKlasse {
attribute bar: Boolean = true;
}
Ersetzen von Triggern
Bisher waren Trigger, die außerhalb von einer Klasse definiert wurden, ein zentraler Bestandteil der Definition von der Reaktion auf Ereignisse. Die neue Syntax definiert so genannte replace triggers als Teil der Attributdeklaration. Die Trigger-Funktion folgt dabei nun den Schlüsselworten on replace.
Beispiel alt:
class MeineKlasse {
attribute bar: Boolean;
}
trigger on MeineKlasse.bar = value {
if (bar == true) {
beep();
}
}
Beispiel neu:
class MeineKlasse {
attribute bar: Boolean on replace {
if (bar == true) { beep();
}
};
}
Beispiel alt mit Initialisierung:
class MeineKlasse {
attribute bar: Boolean = true;
}
trigger on MeineKlasse.bar = value {
if (bar == true) {
beep();
}
}
Beispiel neu mit Initialisierung:
class MeineKlasse {
attribute bar: Boolean = true on replace {
if (bar == true) {
beep();
}
};
}
Kardinalität
Die beliebige Häufigkeit von Attributen wurde bisher mit dem Sternoperator * angegeben und die Werte außerhalb zugewiesen. Nun werden dafür die eckigen Klammern [] verwendet und die Werte direkt in der Klasse zugewiesen.
Beispiel alt:
class MeineKlasse {
attribute names :String*;
}
attribute names = [„Ralph“, „Felix“, „Florian“];
Beispiel neu:
class MeineKlasse {
attribute names :String[] = [„Ralph“, „Felix“, „Florian“];
}
Objektliterale ohne Attribute
Zur Referenzierung von Objektliteralen ohne dessen Attribute konnte man bisher einfach den Klassennamen angeben. In der neuen Syntax werden geschweifte Klammern gefordert.
Beispiel alt:
Frame {
title: „Show MenuSeparator“
height: 180
width: 320
menubar: MenuBar {
menus: Menu {
text: „File“
items: [MenuItem {
text: „New“
}, MenuItem {
text: „Open“
}, MenuItem {
text: „Save“
}, MenuSeparator, MenuItem {
text: „Import“
}]
}
}
visible: true
}
Beispiel neu:
Frame {
title: „Show MenuSeparator“
height: 180
width: 320
menubar: MenuBar {
menus: Menu {
text: „File“
items: [MenuItem {
text: „New“
}, MenuItem {
text: „Open“
}, MenuItem {
text: „Save“
}, MenuSeparator {
}, MenuItem {
text: „Import“
}]
}
}
visible: true
}
Benannte Instanzen
In den bisherigen Versionen von JavaFX Script waren benannten Instanzen mehr oder weniger das, was nun vollqualifizierte Konstanten darstellen (oder Objektliterale).
Beispiel alt:
Frame {
title: „White Frame“
background: white
}
Beispiel neu:
Frame {
title: „White Frame“
background: Color.WHITE
}
Alternatives Beispiel neu:
Frame {
title: „White Frame“
background: Color {
red: 1
green: 1
blue: 1
opacity: 1
}
}
Anonyme Objektliterale
Bisher konnten Sie ein anonymes Objektliteral ohne die Spezifizierung von einen Typ deklarieren . Der Interpreter legte den Typ implizit fest (eine Art der losen Typisierung, wie es auch unter JavaScript oder PHP Einsatz findet, unter Java allerdings ziemlich brutal im Widerspruch zum streng typisierten Konzept stand). In der neuen Version müssen Sie explizit Objektliterale benennen.
Conversion:
Beispiel alt:
accelerator: {
modifier: CTRL
keyStroke: O
}
….
Beispiel neu:
accelerator: Accelerator {
modifier: KeyModifier.CTRL
keyStroke: KeyStroke.O
}
…
Überschreiben von Funktionen nun mit expliziter Angabe des Rückgabetyps
Bisher konnten Sie beim Überschreiben von einer Funktion auf die Angabe des Rückgabetyps verzichten. Nun muss die Signatur der Funktion diesen Rückgabetyp spezifizieren.
Beispiel alt:
class MyWidget extends CompositeNode {
…
function composeNode() {
…
}
}
Beispiel neu:
class MyWidget extends CompositeNode {
…
function composeNode() :Node {
…
}
}
Bidirektionales Binden – with inverse
Das bidirektionales Binden verwendet in der neuen Variante die Syntax with inverse.
Beispiel alt:
… TextField {
value: bind model.firstName
}
…
Beispiel neu:
…
TextField {
value: bind model.firstName with inverse
}
…
Casting von Number nach Integer
Bei der Typumwandlung von Number nach Integer verwendet man in der neuen JavaFX-Variante die Funktion intValue(), um einem Verlust der Genauigkeit vorzubeugen
Beispiel alt:
… var real :Number;
num = 6.42;
var integer :Integer;
integer = real;
…
Beispiel neu:
… var real :Number;
num = 6.42;
var integer :Integer = real.intValue();
…
Vererbung
Bei der Vererbung gibt es in JavaFX Script aktuell ein paar kleinere Probleme, so dass das Schlüsselwort as in einigen Situationen notwendig wird.
Beispiel alt:
class MeineKlasse extends Rectangle {
…
}
…
…
content: Canvas {
content: Foo {
…
}
…
}
…
}
Beispiel neu:
class MeineKlasse extends Rectangle {
…
Old:}
var foo :Foo = Foo {
…
};
…
content: Canvas {
content: foo as Node
…
}
…
}
for-Schleife
Nachdem man in Java selbst ein foreach-Konstrukt eingeführt, aber syntaktisch anders aufgebaut hat, war die syntaktische Abweichung in JavaFX Script ziemlich unglücklich. In der neuen Varianten wurde die Syntax an Java angepasst.
Beispiel alt:
…
for (Integer i = 0; i < element.length; i++) {
System.out.println(element);
}
…
foreach (element in group) {
System.out.println(element);
}
…
Beispiel neu:
…
for (Integer i = 0; i < element.length; i++) {
System.out.println({element});
}
…
for (element in group where element.length() < 4) {
System.out.println({element});
}
…
Das neue API
Das API von JavaFX Script wurde in einigen Bereich reorganisiert. Insbesondere zur GUI. Details lassen sich aber leicht über die JavaFX Script Programming Language API Documentation unter https://openjfx.java.sun.com/current-build/doc/api/index.html nachschlagen. Und natürlich steht auch die offizielle Dokumentation von Sun unter https://java.sun.com/javafx zur Verfügung.
Hier gibt es die Umstiegsanleitung für JavaFX Script auf die Finalversion 1.0 als PDF zum Download
In meiner Seite zu JavaFX – https://www.javafx-buch.de gibt es weitere Infos zu JavaFX.