今回は、制御構文など第3回で触れられなかった文法について説明していきます。
演算子
JavaFX Scriptで使用可能な演算子の一覧を表1に示しました。基本的にJavaとそれほど変わることはありません。また、演算の評価順序もJavaのそれに準拠しています。なお、インタープリタ版では不等号を表す演算子は<>でしたが、1.0では!=に変更されています。
しかし、論理演算子のandやorなど、Javaとは表記が異なる演算子もあります。表記が異なるだけで、使い方はJavaと変わりません。表記も使い方も異なるのが、キャストとシーケンスに対する演算子です。これらはいずれも、第3回ですでに説明していますので、ここでは省略させていただきます。
また、アニメーションで使用するトゥイーン演算子はJavaにはありません。このトゥイーン演算子に関してはアニメーションを解説する回で詳しく触れる予定です。
Javaには存在するのに、JavaFX Scriptでは存在しない演算子には、%=やシフト演算、ビット論理演算などがあります。また、条件演算子の?:もJavaFX Scriptには存在しません。条件演算子に関しては、後述するif文で代用することができます。
表1 JavaFX Scriptでの演算子一覧
演算子の種類 |
演算子 |
説明 |
相当するJavaの演算子 |
オペランドの型 |
結果の型 |
代入演算子 |
= |
代入 |
= |
|
|
複合代入演算子 |
+= |
加算して代入 |
+= |
Integer += Integer |
Integer |
Integer += Number |
Integer |
Number += Integer |
Number |
Number += Number |
Number |
Duration += Duration |
Duration |
-= |
減算して代入 |
-= |
Integer -= Integer |
Integer |
Integer -= Number |
Integer |
Number -= Integer |
Number |
Number -= Number |
Number |
Duration -= Duration |
Duration |
*= |
乗算して代入 |
*= |
Integer *= Integer |
Integer |
Integer *= Number |
Integer (計算はNumberを使用) |
Number *= Integer |
Number |
Number *= Number |
Number |
Duration *= Integer |
Duration |
Duration *= Number |
Duration |
/= |
除算して代入 |
/= |
Integer /= Integer |
Integer |
Integer /= Number |
Integer (計算はNumberを使用) |
Number /= Integer |
Number |
Number /= Number |
Number |
Duration /= Integer |
Duration |
Duration /= Number |
Duration |
トゥイーン演算子 |
=> |
トゥイーン |
なし |
Duration => Duration |
Duration |
二項論理演算子 |
and |
条件論理積 |
&& |
Boolean and Boolean |
Boolean |
or |
条件論理和 |
|| |
Boolean or Boolean |
Boolean |
単項論理演算子 |
not |
否定 |
! |
not Boolean |
Boolean |
型演算子 |
instanceof |
型の比較 |
instanceof |
Object instanceof 型 |
Boolean |
as |
キャスト |
(型) |
Object as 型 |
(型で指定した)Object |
関係演算子 |
== |
等しい |
== |
Object == Object |
Boolean |
!= |
等しくない |
!= |
Object != Object |
Boolean |
< |
左辺の値が右辺の値より小さい |
< |
Integer < Integer |
Boolean |
Integer < Number |
Number < Integer |
Number < Number |
Duration < Duration |
<= |
左辺の値が右辺の値以下 |
<= |
Integer <= Integer |
Boolean |
Integer <= Number |
Number <= Integer |
Number <= Number |
Duration <= Duration |
> |
左辺の値が右辺の値より大きい |
> |
Integer > Integer |
Boolean |
Integer > Number |
Number > Integer |
Number > Number |
Duration > Duration |
>= |
左辺の値が右辺の値以上 |
>= |
Integer >= Integer |
Boolean |
Integer >= Number |
Number >= Integer |
Number >= Number |
Duration >= Duration |
二項算術演算子 |
+ |
加算 |
+ |
Integer + Integer |
Integer |
Integer + Number |
Number |
Number + Integer |
Number |
Number + Number |
Number |
Duration + Duration |
Duration |
- |
減算 |
- |
Integer - Integer |
Integer |
Integer - Number |
Number |
Number - Integer |
Number |
Number - Number |
Number |
Duration - Duration |
Duration |
* |
乗算 |
* |
Integer * Integer |
Integer |
Integer * Number |
Number |
Number * Integer |
Number |
Number * Number |
Number |
Integer * Duration |
Duration |
Number * Duration |
Duration |
Duration * Integer |
Duration |
Duration * Number |
Duration |
/ |
除算 |
/ |
Integer / Integer |
Integer |
Integer / Number |
Number |
Number / Integer |
Number |
Number / Number |
Number |
Duration / Integer |
Duration |
Duration / Number |
Duration |
Duration / Duration |
Number |
mod |
除算の余り |
% |
Integer mod Integer |
Integer |
前置単項演算子 |
- |
符号の反転 |
- |
- Integer |
Integer |
- Number |
Number |
- Duration |
Duration |
sizeof |
シーケンスのサイズ |
length |
sizeof シーケンス |
Integer |
reverse |
シーケンスの反転 |
なし |
reverse シーケンス |
シーケンス |
++ |
インクリメント |
++ |
++Integer |
Integer |
++Number |
Number |
-- |
デクリメント |
-- |
--Integer |
Integer |
--Number |
Number |
indexof |
シーケンスのインデックス |
なし |
|
Index |
後置演算子 |
++ |
インクリメント |
++ |
Integer++ |
Integer |
Number++ |
Number |
-- |
デクリメント |
-- |
Integer-- |
Integer |
Number-- |
Number |
構文
ブロック構文
ブロック構文は波括弧でくくられた複数の式からなります。複数の式の最後の式がブロック構文の値となります。
第3回のオブジェクトの生成で、アトリビュートの初期化に次のような構文を使用しました。
sumアトリビュートに値を代入するため、波括弧でくくられた複数の式を使用しています。これがブロック構文です。sumにはブロック構文の最後の式、つまりtmpSumの値が代入されます。
このブロック構文はアトリビュートの初期化に限らず、変数に代入することや関数の引数などにも使用することが可能です。たとえば、リスト2のスクリプトは正月までの日数の計算処理をブロック構文で実現しています(import文は省略してあります)。
赤字の部分がブロック構文で表した部分です。ここでは、Javaのjava.util.Calendarクラスを使って日にちを表しています。スクリプトを実行した日から大晦日までの日数を求め、それに1を足すことで正月までの日数を求めています。
このスクリプトの実行結果を図1に示します。実行した日は12/10だったため、正月までは22日と表示されます。
if 文
if文は条件により処理を切り替えるために使用します。
表記はJavaとほぼ同じですが、処理はJavaと少し異なります。というのも、JavaFX Scriptでは、条件によって切り替えるのは括弧でくくられた複数の文ではなく、ブロック構文であるためです。つまり、JavaFX Scriptではリスト3のような表記を行うこともできます。
valueが偶数であれば変数colorにはColor.REDが代入され、奇数であればColor.BLUEが代入されます。
また、Javaの条件演算子?:のように、1行に記述することも可能です。リスト3と同内容のスクリプトを1行で記述したものが、リスト4のスクリプトです。
もちろん、Javaのように処理だけを記述することもできます。
また、else ifを使用することで、複数の条件式を表記することも可能です。
なお、JavaFX Scriptにはswitch文はないので、if...else if...で代用します。
ここで、if文の使用例として、下駄を投げて天気予報をしてみましょう。
この例では2つのif文があります。青字の方が単に処理を条件によって切り替えているのに対し、赤字の方は条件演算子のように使用しています。青字の方はグラデーションで使用する色を条件によって変化させています。一方の赤字の方は、条件によってTextオブジェクトのcontentアトリビュートに代入する文字列を変化させています。
スクリプトは乱数によって、背景のグラデーションと表示させる文字列を変化させます。もちろん、乱数で天気を予想しているだけなので、当たるかどうかは天のみ知るといったところです。
では、実際に実行してみましょう。
for文
JavaFX Scriptのfor文は、Javaの拡張for文のような使い方をします。
Javaで拡張for文が使用できるのは、java.util.ArrayListクラスのようにjava.lang.Iterableインタフェースを実装したクラスと配列ですが、JavaFX Scriptではシーケンスのみです。
また、シーケンスの個々の要素を代入する変数と、シーケンスの間にはinを記述します。なお、valueの型名は明らかなので、省略できます。
リスト8のスクリプトを実行すると、0から10までを出力します(図3)。
break文やcontinue文も、Javaと同様に使用することができます。
xが5の時、continue文によりprintln関数をコールすることなく、次の繰り返しに制御を移動させます。xが8の時には、break文によりfor文を脱出します。スクリプトを実行すると、5は出力されません。また、8以上も出力されないことがわかります(図4)。
このようにbreak文とcontinue文を使用することができますが、Javaのようにラベルつきのbreakやcontinueは使用できません。
if文と同じく、for文も並括弧でくくられた複数の文を繰り返し実行するのではなく、ブロック構文を繰り返し実行することになります。そして、その結果はシーケンスとなります。
リスト10のスクリプトはシーケンス[0..10]の各要素を2倍したシーケンスを作成します。実行した結果を図5に示します。
ループのインデックスを使用したい場合は、第3回で説明したindexof演算子を使用します。
ではリスト11を実行してみましょう。
for文の括弧の中には複数のシーケンスを書くことができます。この記述法は、for文を二重に記述したものと等価です。
リスト12のスクリプトはリスト13と同じ結果になります。
実行結果を図7に示します。
break文やcontinue文はどうなるでしょうか。リスト14のスクリプトでは、yが1の時にbreakでfor文を脱出しています。
しかし、実行すると予想に反した動作をします(図8)。
これはバグとして登録されているので、近いうちに修正されるはずです。
JavaFXのバグはJavaFX-JIRAで管理されており、サインアップすると誰でもバグの登録をすることができます。ちなみに、上記のバグはJFXC-2504として管理されています(参照するのもサインアップが必要です)。
最後にfor文の簡単なサンプルを示しましょう。複数の円を描画するサンプルです。
変数circlesにはfor文によりCircleクラスのシーケンスが代入されます。個々のCircleオブジェクトは変数decFlagと変数numによって、位置と半径が決まります。半径は一度大きくなってから、再び小さくなるようにしてみました。実行結果を図9に示します。
while文
while文はJavaと記述方法が同じです。ブロック構文の値は取らないので、for文のようにシーケンスに代入することはできません。
実行結果を図10に示します。
また、break文、continue文も使用することができます。
例外
JavaFX Scriptでも例外を扱うことができます。使用法もJavaの例外と同じです。しかし、チェックされる例外(checked exception)であっても、try ... catchは必須ではありません。たとえば、リスト17のスクリプトではjava.io.FileNotFoundException例外やjava.io.IOException例外がスローされる可能性がありますが、catchを書く必要はありません。
とはいうものの、頑健なスクリプトを記述するのであれば、必要に応じてtry ... catchを書くべきであると筆者は考えています。
なお、インタープリタ版では任意のオブジェクトをスローできましたが、1.0ではJavaと同じくjava.lang.Throwableクラスだけになりました。
さて、今回は演算子と構文について説明を行いました。制御構文は通常ロジックで使用しますが、ブロック構文を使用することで、宣言的文法と合わせて使うことが可能になります。ぜひご活用ください。
次回は、JavaFX ScriptでSwingのコンポーネントを使う方法を紹介します。