ITPUB??ì3
ITPUB论坛 » WEB 2.0技术 » JavaFX编程语言语法指南

新一届的微软MVP评选已经开始,欢迎各位推荐!

标题: JavaFX编程语言语法指南
离线 jieforest
磨刀霍霍向猪羊


精华贴数 2
个人空间 0
技术积分 5270 (253)
社区积分 1443 (750)
注册日期 2005-3-31
论坛徽章:8
ITPUB元老会员2007贡献徽章授权会员生肖徽章2007版:马2008年新春纪念徽章生肖徽章2007版:猴
生肖徽章2007版:鸡ITPUB新首页上线纪念徽章    

发表于 2007-5-13 10:54 
JavaFX编程语言语法指南

The JavaFX Script Programming Language
Last Updated: May 2007
The JavaFX Script™ (hereinafter referred to as JavaFX) language is a declarative and statically typed programming language. It has first-class functions, declarative syntax, list-comprehensions, and incremental dependency-based evaluation. The JavaFX Script language makes intensive use of the Java2D swing GUI components and allows for easy creation of GUIs.

This document gives an informal description of the JavaFX Script programming language.

Contents:
Basic Types
Calling Java Objects
Variables
Functions, Arrays, Expressions, and Operations
Modifying Arrays
Insert Statement
into
before, after
Delete Statement
Querying Arrays
Expressions
String Literals and String Expressions
Quoted Identifiers
Range Expression
String, Number and Date Formatting
Operations
Expression Statement
If Statement
While Statement
Try Statement
For Statement
Return Statement
Throw Statement
Break and Continue Statements
Do Statement
do later
Classes and Objects
Attribute Declarations
Object Literals
Update Triggers
Creation Triggers
Insert Triggers
Delete Triggers
Replace Triggers
Incremental and Lazy Evaluation
Reflection
Extents and Enumerations
top



Basic Types
The JavaFX programming language provides four primitive types: String, Boolean, Number, and Integer. These types correspond to Java types as follows:


JavaFX Java
String java.lang.String
Boolean java.lang.Boolean
Number java.lang.Number
Integer byte,short,int,long,BigInteger


Example:

        var s = "Hello";
        s.toUpperCase(); // yields "HELLO";
        s.substring(1);  // yields "ello";
        var n = 1.5;
        n.intValue();    // yields 1
        (1.5).intValue();    // yields 1
        s.substring(n);  // yields "ello"
        var b = true;
        b instanceof Boolean; // yields true

Coercions are automatically performed on numeric types when passing arguments or return values to/from Java methods. In addition, implicit truncating coercions are performed when converting Numbers to Integers.

top

Calling Java Objects
JavaFX programs can import Java classes, create new Java objects, call their methods, and implement Java interfaces. The following code snippet provides an example:

        import javax.swing.JFrame;
        import javax.swing.JButton;
        import java.awt.event.ActionListener;
        import java.lang.System;

        var frame = new JFrame();
        var button = new JButton("Press me";
        frame.getContentPane().add(button);
        button.addActionListener(new ActionListener() {
                operation actionPerformed(event) {
                    System.out.println("You pressed me";
                }
            });
        frame.pack();
        frame.setVisible(true);

Running the above program displays the following on the screen:



Of course, this isn't the preferred way of creating GUI's in JavaFX. The following JavaFX code achieves the same effect:

         Frame {
              content: Button {
                   text: "Press Me"
                   action: operation() {
                        System.out.println("You pressed me";
                   }
              }
              visible: true
         }
top

Variables
In JavaFX, the var keyword introduces a new variable. You may specify the type of a variable in its declaration. However, that's optional in JavaFX. If you don't specify the type, the JavaFX interpreter infers the variable's type from its use. A variable declaration takes the form

        var variableName : typeName [?,+,*] = initializer;

You may use one of the ?, +, or * operators to denote the cardinality of the variable, as follows:


Operator Meaning
? Optional (i.e, may be null)
+ One or more
* Zero or more

Example:

        var nums:Number* = [1,2,3];
The above example declares a new variable named nums whose value is defined to consist of zero or more instances of type Number and whose initial value is [1,2,3].

The :typeName, [?,+,*], and = initializer portions of the declaration are optional, so the following is equivalent to the above:         var nums = [1,2,3];
top


Functions, Arrays, Expressions, and Operations
JavaFX functions represent a pure functional subset of the JavaFX programming language. The body of a function may only contain a series of variable declarations and a return statement. JavaFX also provides procedures (called operations, see below) which may contain any number of statements including conditional statements, looping statements, try/catch, etc. The order in which the functions are given is not in general significant. Following is a very simple example of a functional program:

        function z(a,b) {
           var x = a + b;
           var y = a - b;
           return sq(x) / sq (y);
        }

        function sq(n) {return n * n;}

        function main() {
           return z(5, 10);
        }

There are no mandatory type declarations, although the language is statically typed (see more details later).

The most commonly used data structure is the array, which in JavaFX is written with square brackets and commas, e.g.:         var week_days = ["Mon","Tue","Wed","Thur","Fri"];
        var days = [week_days, ["Sat","Sun"]];
Arrays represent sequences of objects. In JavaFX arrays are not themselves objects, however, and do not nest. Expressions that produce nested arrays (as in the initialization of "days" above) are automaticallly flattened, i.e:

         days == ["Mon","Tue","Wed","Thur","Fri","Sat","Sun"]; // returns true
The size of an array may be determined with the JavaFX sizeof operator:

         var n = sizeof days; // n = 7


There is a shorthand notation using ".." for arrays whose elements form an arithmetic series. Here for example are definitions of the factorial function, and of a number "result" which is the sum of the odd numbers between 1 and 100         function fac(n) {return product([1..n]);}
        var result = sum([1,3..100]);
The elements of an array must all be of the same type.

Arrays may be indexed as in Java:

        var wednesday = days[2];

In JavaFX the [] operator also expresses selection (similar to its use in XPath). In this case, the expression contained in the [] is a boolean expression. Such an expression returns a new array containing only those elements that satisfy the predicate contained in the [].

As in XPath, within the predicate contained inside the [] operator, the context object may be accessed with the dot operator, for example:

        var nums = [1,2,3,4];
        var numsGreaterThanTwo = nums[. > 2]; // yields [3, 4]

Alternatively a variable may be declared for the context object. For example, this is equivalent to the above statement:

        numsGreaterThanTwo = nums[n|n > 2];

The JavaFX indexof operator returns the ordinal position of an element within an array (like the position() function in XPath).

The car and cdr of a list may be expressed using selection expressions like this:

        function car(list) {return list[indexof . == 0];}
        function cdr(list) {return list[indexof . > 0];}

Of course car can be expressed more succinctly as simply:

        function car(list) {return list[0];}

Examples:

        var list = [1..10];
        car(list); // yields 1
        cdr(list); // yields [2,3,4,5,6,7,8,9,10]
In JavaFX, the empty array [] and null are synonymous, i.e:

        [] == null // yields true
        sizeof null // yields 0
top

Modifying Arrays
In addition to the assignment operator (=), JavaFX provides data modification operators (insert and delete) similar in syntax and semantics to those in the draft XQuery-Update specification as follows:

Insert Statement
The insert statement can take any of the following forms:


        insert Expression1 [as first | as last] into Expression2
        insert Expression1 before Expression2
        insert Expression1 after Expression2

The insert statement inserts the items returned by evaluating Expression1 into the location indicated by remainder of the statement as follows:

into

Expression2 must refer to an attribute or variable. If Expression2 refers to a single valued attribute then the effect of the insert is the same as if the assignment operator were used.

If as first is specified, the insertion location is before the first element of the list indicated by Expression2. If as last is specified, the insertion location is after the last element of the list indicated by Expression2. If neither as first nor as last is specified explicitly, then as last is used as the default.

Examples:

        var x = [1,2,3];
        insert 12 into x; // yields [1,2,3,12]
        insert 10 as first into x; // yields [10,1,2,3,12]
        insert [99,100] as last into x; // yields [10,1,2,3,12,99,100]

before, after

Expression2 must be a selection expression over an attribute or variable. If before is specified, the insertion location is before the selected elements. If after is specified the insertion location is after the selected elements.

Examples:


        var x = [1,2,3];
        insert 10 after x[. == 10]; // yields [1,2,3,10]
        insert 12 before x[1]; // yields [1,12,2,3,10]
        insert 13 after x[. == 2]; // yields [1, 12, 2, 13, 3, 10];
top

Delete Statement
The Delete statement takes one of the following forms:


        delete variable
        delete Expression.attribute
        delete variable[predicate]
        delete Expression.attribute[predicate]

The first two forms remove all elements from a variable or attribute - which is equivalent to assigning [] or null to the variable or attribute. The latter two forms remove only those elements that match the predicate.

Examples:


        var x = [1,2,3];
        insert 10 into x; // yields [1,2,3,10]
        insert 12 before x[1]; // yields [1,12,2,3,10]
        delete x[. == 12]; // yields [1,2,3,10]
        delete x[. >= 3]; // yields [1,2]
        insert 5 after x[. == 1]; // yields [1,5,2];
        insert 13 as first into x; // yields [13, 1, 5, 2];
        delete x; // yields []
top

Querying Arrays
JavaFX supports list comprehensions as in functional languages like Miranda and Haskell, but with a familiar syntax that should be easily understood by Java programmers, namely the JavaFX select and foreach operators.

Here is an example:

        class Album {
            attribute title: String;
            attribute artist: String;
            attribute tracks: String*;
        }

        var albums =
        [Album {
             title: "A Hard Day's Night"
             artist: "The Beatles"
             tracks:
             ["A Hard Day's Night",
              "I Should Have Known Better",
              "If I Fell",
              "I'm Happy Just To Dance With You",
              "And I Love Her",
              "Tell Me Why",
              "Can't Buy Me Love",
              "Any Time At All",
              "I'll Cry Instead",
              "Things We Said Today",
              "When I Get Home",
              "You Can't Do That"]
        },
        Album {
              title: "Circle Of Love"
              artist: "Steve Miller Band"
              tracks:
              ["Heart Like A Wheel",
                "Get On Home",
                "Baby Wanna Dance",
                "Circle Of Love",
                "Macho City"]
        }];

        // Get the track numbers of the albums' title tracks

        // using the select operator:

        var titleTracks =
            select indexof track + 1 from album in albums,
                      track in album.tracks
                          where track == album.title; // yields [1,4]

       // the same expressed using the foreach operator:

        titleTracks =
            foreach (album in albums,
                      track in album.tracks
                          where track == album.title)
                indexof track + 1;  // also yields [1,4]


A list comprehension consists of one or more input lists, an optional filter and a generator expression. Each source list is associated with a variable. The result of the list comprehension is a new list which is the result of applying the generator to the subset of the cartesian product of the source lists' elements that satisfy the filter.

List comprehensions give a concise syntax for a rather general class of iterations over lists.

Another simple example of a list comprehension is:

        select n*n from n in [1..100]

This is a list containing (in order) the squares of all the numbers from 1 to 100. Note that "n" is a local variable of the above expression.

The use of a filter is shown by the following definition of a function which takes a number and returns a list of all its factors,


        function factors(n) {
            return select i from i in [1..n/2] where n % i == 0;
        }
top

Expressions
JavaFX supports the following operators:


Operator Meaning Java Equivalent

Relational Operators
== equality ==
<> inequality !=
< less than <
> greater than >
<= less than or equal <=
>= greater than or equal >=

Boolean Operators  
and logical and &&
or logical or ||
not logical negation !

Arithmetic Operators
+ addition +
- subtraction; unary negation -
* multiplication *
/ division /
% remainder %
+= add and assign +=
-= subtract and assign -=
*= multiply and assign *=
/= divide and assign /=
%= remainder and assign %=

Other Operators
sizeof array length n/a
indexof ordinal position n/a
if e1 then e2 else e3 conditional expression e1 ? e2 : e3  
select list comprehension n/a
foreach list comprehension n/a
new allocation new
op() function/operation call n/a
x.op() member function/operation call x.op()
instanceof type check instanceof
this self access this
. attribute access, context access ., n/a
bind [lazy] incremental [lazy] evaluation n/a
: eager initialization n/a
[] array selection []
format as String formatting n/a
<<>> Identifier quotes n/a
{} String expression n/a
(expr) grouping (expr)
reverse reverses a list n/a
[number1,next..number2] numeric range n/a

Some Examples:

         import java.lang.System;
         import java.lang.Math;

         var x = 2;
         var y = 4;
         var a = true;
         var b = false;
         System.out.println(x == y);  // prints false
         System.out.println(x <> y);  // prints true
         System.out.println(x < y);   // prints true
         System.out.println(x > y);   // prints true
         System.out.println(x >= y);  // prints false
         System.out.println(x <= y);  // prints true
         System.out.println(x + y);   // prints  6
         System.out.println(x - y);   // prints  -2
         System.out.println(x * y);   // prints  8
         System.out.println(x / y);   // prints  0.5
         System.out.println(x % y);   // prints  2
         System.out.println(a and b); // prints  false
         System.out.println(a or b);  // prints  true
         System.out.println(not a);   // prints  false
         System.out.println(sizeof [x,y]);   // prints  2
         System.out.println([x,y][indexof . == 0]);   // prints  2
         System.out.println(if a then x else y); // prints 2
         System.out.println(select q from q in [x, y] where q > 3); prints 4
         System.out.println(foreach(q in [x, y] where q < 3) q); prints 2
         System.out.println(Math.max(x, y)); // prints 4
         System.out.println("abc".toUpperCase()); // prints ABC
         System.out.println(x instanceof Number); // prints true
         x = 10;
         System.out.println(x); // prints 10
top

String Literals and String Expressions
In JavaFX, a literal character string is specified with single quotes, e.g.

        var s = 'Hello';

or with double quotes:         var s = "Hello";

In the latter case, JavaFX expressions may be embedded using {}, e.g

        var name = 'Joe';
        var s = "Hello {name}"; // s = 'Hello Joe'

The embedded expression may itself contain quoted strings (which, in turn, may contain further embedded expressions), e.g

        var answer = true;
        var s = "The answer is {if answer then "Yes" else "No"}"; // s = 'The answer is Yes'

Unlike in Java, JavaFX double-quoted String literals can contain newlines:

        var s = "This
                 contains
                 new lines";
top

Quoted Identifiers
In JavaFX, any sequence of characters (including whitespace) contained in french quotes <<>> is treated as an identifier. This allows you to use JavaFX keywords (or other normally illegal identifiers) as class, variable, function, or attribute names, e.g.

        var <<while>> = 100;
It also makes it possible to call Java methods whose names are the same as JavaFX keywords, for example:

        import javax.swing.JTextArea;

        var textArea = new JTextArea();
        textArea.<<insert>>("Hello", 0);
top

Range Expression
As mentioned above you can define an array of numeric values that form an arithmetic series using the following syntax:

            [number1..number2]
Such an expression defines an array whose elements consist of the integers from number1 to number2 (inclusive).

For example:

            var nums = [0..3];
            System.out.println(nums == [0,1,2,3]); // prints true

By default the interval between the values is 1 but it's also possible to specify a different interval by including the next number in the sequence after number1 separated by a comma. For example, the following expression defines an array consisting of the odd numbers between 1 and 10:

            [1,3..10]
If number1 is greater than number2 a descending series is created:

            var nums = [3..0];
            System.out.println(nums == [3,2,1,0]); // prints true
top

String, Number, and Date Formatting
JavaFX has a built-in String formatting operator (format as), which has the following syntax:

        expr format as directive
The format as operator supports java.text.DecimalFormat, java.text.SimpleDateFormat, and java.util.Formatter formatting directives. If the formatting directive starts with %, then java.util.Formatter is used, otherwise if expr is of type Number then java.text.DecimalFormat is used, otherwise if expr is of type java.util.Date then java.text.SimpleDateFormat is used. The directive operand is syntactically an identifier, not an expression. This allows the content of directive to be statically checked for correctness at compile time.

Examples:         import java.util.Date;

        100.896 format as <<%f>>; // yields '100.896000'
        31.intValue() format as <<%02X>>; // yields '1F'
        var d = new Date();
        d format as <<yyyy-MM-dd'T'HH:mm:ss.SSSZ>>; // yields '2005-10-31T08:04:31.323-0800'
        0.00123 format as <<00.###E0>>; // yields '12.3E-4'
top

Operations
In JavaFX, procedures are declared with the operation keyword. For example:

        import java.lang.StringIndexOutOfBoundsException;

        operation substring(s:String, n:Number): String {
              try {
                  return s.substring(n);
              } catch (e:StringIndexOutOfBoundsException) {
                  throw "sorry, index out of bounds";
              }
        }

The above example defines a new procedure called "substring" with two arguments, the first named "s" of type "String", the second named "n" of type "Number", returning type "String".

In addition to the assignment, delete, and insert statements mentioned above, the following statements are possible inside the body of an operation :

Expression Statement
A primary expression may be used as a statement, for example:

       System.out.println("Hello World!";
top

If Statement
The JavaFX if statement is like Java's except that curly braces are always required around the then and else clauses, unless the the else clause is another if statement.

Example:

       if (condition1) {
           System.out.println("Condition 1";
       } else if (condition2) {
           System.out.println("Condition2";
       } else {
           System.out.println("not Condition 1 or Condition 2";
       }
top

While Statement
The JavaFX while statement is like Java's except that curly braces are always required around the body.

Example:

       var i = 0;
       while (i < 10) {
           if (i > 5) {
              break;
           }
           System.out.println("i = {i}";
           i += 1;
       }
top

Try Statement
The JavaFX try statement is like Java's but with JavaFX variable declaration syntax. Note: in JavaFX any object can be thrown and caught, not just those that extend java.lang.Throwable.

Example:

       try {
          throw "Hello";
       } catch (s:String) {
          System.out.println("caught a String: {s}";
       } catch (any) {
          System.out.println("caught something not a String: {any}";
       } finally {
          System.out.println("finally...");
       }
top

For Statement

The header of the JavaFX for statement uses the same syntax as the foreach list comprehension operator. However, in this case the body of the statement is executed for each element generated by the list comprehension.

Examples:

        for (i in [0..10]) {
             System.out.println("i = {i}");
        }

        // print only the even numbers using a filter
        for (i in [0..10] where i % 2 == 0) {
             System.out.println("i = {i}");
        }

        // print only the odd numbers using a range expression
        for (i in [1,3..10]) {
             System.out.println("i = {i}");
        }

        // print the cartesian product
        for (i in [0..10], j in [0..10]) {
             System.out.println(i);
             System.out.println(j);
        }
top

Return Statement
The JavaFX return statement is like Java's:
Example:

       operation add(x, y) {
           return x + y;
       }
top

Throw Statement
The JavaFX throw statement is like Java's. However, any object may be thrown, not just those that extend java.lang.Throwable.
Examples:

       import java.lang.Exception;

       operation foo() {
           throw new Exception("this is a java exception");
       }

       operation bar() {
           throw "just a string";
       }
top

Break and Continue Statements
The JavaFX break and continue statements are like Java's, however labels are not supported. As in Java, break and continue must appear inside the body of a while or for statement.
Examples:

       operation foo() {
          for (i in [0..10]) {
              if (i > 5) {
                  break;
              }
              if (i % 2 == 0) {
                  continue;
              }
              System.out.println(i);
          }
       }

       operation bar() {
           var i = 0;
           while (i < 10) {
               if (i > 5) {
                   break;
               }
               if (i % 2 == 0) {
                   continue;
               }
               System.out.println(i);
               i += 1;
           }
       }
top


只看该作者    顶部
离线 jieforest
磨刀霍霍向猪羊


精华贴数 2
个人空间 0
技术积分 5270 (253)
社区积分 1443 (750)
注册日期 2005-3-31
论坛徽章:8
ITPUB元老会员2007贡献徽章授权会员生肖徽章2007版:马2008年新春纪念徽章生肖徽章2007版:猴
生肖徽章2007版:鸡ITPUB新首页上线纪念徽章    

发表于 2007-5-13 10:54 
Do Statement
The JavaFX do statement allows you to execute a block of JavaFX code in a background thread while allowing the AWT Event Dispatch Thread to continue processing events, thereby preventing the UI from appearing to hang. Currently, this is implemented by using java.awt.EventQueue to pump events while the background thread is executing. Normally, all JavaFX code executes in the AWT Event Dispatch Thread. Only code contained in the body of a do statement is allowed to execute in another thread. Such code must only access Java objects (and those objects must handle their own thread synchronization, if necessary).

Example:

        import java.net.URL;
        import java.lang.StringBuffer;
        import java.lang.System;
        import java.io.InputStreamReader;
        import java.io.BufferedReader;



        // in the AWT EDT
        var result = new StringBuffer();

        do {
            // now in a background thread
             var url = new URL("http://www.foo.com/abc.xml";
             var is = url.openStream();
             var reader = new BufferedReader(new InputStreamReader(is));
             var line;
             while (true) {
                  line = reader.readLine();
                  if (line == null) {
                       break;
                  }
                  result.append(line);
                  result.append("\n";
             }
        }
        // now back in the EDT
        System.out.println("result = {result}";
In the above example, the green code which is executing in the EDT appears to be blocked during the execution of the body of the do statement (the red code). However, a new event dispatch loop is created on the stack while waiting for the background thread to complete. As a result, GUI events continue to be processed while the do statement is executing. Unfortunately, this isn't a perfect solution, however, since it can cause multiple event dispatch loops to build up on the stack - in the degenerate case causing a stack overflow exception.

top

do later
The do statement has a second form (do later) that allows for asynchronous execution of its body in the EDT rather than synchronous execution in a background thread (providing the functionality of java.awt.EventQueue.invokeLater) Here's an example:

        import java.lang.System;
        var saying1 = "Hello World!";
        var saying2 = "Goodbye Cruel World!";
        do later {
             System.out.println(saying1);
        }
        System.out.println(saying2);

Running this code produces the following output:         Goodbye Cruel World!
        Hello World!
top

Classes and Objects
The JavaFX syntax for specifying a class is the class keyword followed by the class name, optionally the extends keyword, and a comma separated list of the names of base classes, an open curly brace, a list of attributes, functions, and operations that each end in a semicolon, and a closing curly brace.

Here is an example:

        class Person {
           attribute name: String;
           attribute parent: Person inverse Person.children;
           attribute children: Person* inverse Person.parent;
           function getFamilyIncome(): Number;
           function getNumberOfChildren(): Number;
           operation marry(spouse: Person);
        }
         Attributes are declared using the attribute keyword followed by the attribute's name, a colon, the attribute's type, optionally a cardinality specification (? meaning optional, * meaning zero or more, or + meaning one or more), and an optional inverse clause specifying a bidirectional relationship to another attribute in the class of the attributes' type, and terminated with a semicolon.

        attribute AttributeName : AttributeType Cardinality inverse ClassName.InverseAttributeName;
If the inverse clause is present the JavaFX interpreter will automatically perform updates (insert or delete or replace depending on the kind of update and cardinalities of the attributes) on the inverse attribute whenever the attribute's value is modified.

Multi-valued attributes (i.e. those declared with the * or + cardinality specifiers) are represented as arrays, and can be accessed via the [] operator and updated with the insert and delete operators.

Unlike Java methods, the bodies all JavaFX member operations and member functions are defined outside of the class declaration, for example, like this:

       function Person.getNumberOfChildren() {
            return sizeof this.children;
       }
         Parameter and return types are required in the declaration of operations and functions in the class declaration but may be omitted in their definitions.

top

Attribute Declarations
In JavaFX, it's possible to declare initial values for attributes. The initializers are evaluated in the order the attributes are specified in the class declaration in the context of the newly created object:

       import java.lang.System;

       class X {
            attribute a: Number;
            attribute b: Number;
       }

       attribute X.a = 10;
       attribute X.b = -1;

       var x = new X();
       System.out.println(x.a); // prints 10
       System.out.println(x.b); // prints -1
         It is also possible to declare an incrementally evaluated expression as the value of an attribute using the bind operator:

       import java.lang.System;

       class X {
            attribute a: Number;
            attribute b: Number;
            attribute c: Number;
       }

       attribute X.a = 10;

       attribute X.b = bind a + 10;
       attribute X.c = bind lazy b + 10;


       var x = new X();
       System.out.println(x.a); // prints 10
       System.out.println(x.b); // prints 20
       System.out.println(x.c); // prints 30
       x.a = 5;
       System.out.println(x.a); // prints 5
       System.out.println(x.b); // prints 15
       System.out.println(x.c); // prints 25
         top

Object Literals
JavaFX objects may be allocated using a declarative syntax consisting of the name of the class followed by a curly brace delimited list of attribute initializers. Each initializer consists of the attribute name followed by a colon, followed by an expression which defines its value (but see below regarding JavaFX's support for incremental evaluation in this context). Here is an example:

         var chris = Person {
             name: "Chris"
             children:
             [Person {
                 name: "Dee"
             },
             Person {
                 name: "Candice"
             }]
       };
         Java object allocation syntax is also supported. In the case of Java classes, you can pass arguments to the class's constructor as in Java:

        import java.util.Date;
        import java.lang.System;

        var date1 = new Date(95, 4, 23); // call a java constructor
        var date2 = Date { // create the same date as an object literal
             month: 4
             date: 23
             year: 95
        };
        System.out.println(date1 == date2);  // prints true
         In JavaFX, it's possible to declare local variables inside an object literal. Such variables are only visible within the scope of the object literal itself. In addition, a variable referring to the object being initialized may be declared by using the var keyword as a pseudo-attribute, for example:

        var chris = Person {
             var: me
             name: "Chris"
             var child1 = Person {
                  name: "Dee"
                  parent: me
             }
             var child2 = Person { name: "Candice" }
             children: [child1, child2]
       };
         top

Update Triggers
JavaFX classes don't have constructors, and JavaFX attributes don't have "setters" like Java bean properties. Instead, JavaFX provides SQL-like triggers that allow you to handle data modification events.

Triggers are introduced with the trigger keyword.

A trigger consists of a header and a body. The header specifies the type of event the trigger applies to. The body of the trigger is a procedure that executes whenever the specified event occurs. Inside the body you can use any of the statements available inside the body of an operation. Triggers also behave like member functions/operations, in that the context object is accessible inside the body via the this keyword.

top

Creation Triggers
You can perform an action in the context of a newly created object by specifying a creation "trigger", like this:

          import java.lang.System;

         class X {
              attribute nums: Number*;
         }

         trigger on new X {
              insert [3,4] into this.nums;
         }

         var x = new X();
         System.out.println(x.nums == [3,4]); // prints true
         This example defines a trigger that will be executed whenever a new instance of the X class is created. In this case it just assigns an initial value to the nums attribute.

top

Insert Triggers
You can perform an action whenever an element is inserted into a multi-valued attribute by specifying an insert trigger, like this:

         import java.lang.System;

         class X {
              attribute nums: Number*;
         }

         trigger on insert num into X.nums {
              System.out.println("just inserted {num} into X.nums at position {indexof num}";
         }
         var x = new X();
         insert 12 into x.nums; // prints just inserted 12 into X.nums at position 0
         insert 13 into x.nums; // prints just inserted 13 into X.nums at position 1
         In the above example, "num" is the name of a variable that will contain a reference to the element being inserted (you can name the variable whatever you like). The context index of the variable (returned by the indexof operator) corresponds to the insertion point.

top

Delete Triggers
You can perform an action whenever an element is deleted from a multi-valued attribute by specifying a delete trigger, like this:

         import java.lang.System;

         class X {
              attribute nums: Number*;
         }

         trigger on delete num from X.nums {
              System.out.println("just deleted {num} from X.nums at position {indexof num}";
         }

         var x = X {
              nums: [12, 13]
         };

         delete x.nums[1]; // prints just deleted 13 from X.nums at position 1
         delete x.nums[0]; // prints just deleted 12 from X.nums at position 0
         In the above example, "num" is the name of a variable that will contain a reference to the element being deleted (you can name the variable whatever you like). The context index of the variable (returned by the indexof operator) corresponds to the deletion point.


top

Replace Triggers
You can perform an action whenever the value of a single-valued attribute or an element of a multi-valued attribute is replaced, like this:

         import java.lang.System;

         class X {
              attribute nums: Number*;
              attribute num: Number?;
         }

         trigger on X.nums[oldValue] = newValue {
              System.out.println("just replaced {oldValue} with {newValue} at position {indexof newValue} in X.nums";
         }

         trigger on X.num[oldValue] = newValue {
              System.out.println("X.num: just replaced {oldValue} with {newValue}";
         }

         var x = X {
              nums: [12, 13]
              num: 100
         };
         x.nums[1] = 5; // prints just replaced 13 with 5 at position 1 in X.nums
         x.num = 3; // prints X.num: just replaced 100 with 3
         x.num = null;  // prints X.num: just replaced 3 with null
         In the above examples, "oldValue" and "newValue" are the names of variables that contain references to the previous and current values of the element being replaced (you can name the variables whatever you like). The context index of the variable (returned by the indexof operator) corresponds to the ordinal position of the element being replaced.

top

Incremental and Lazy Evaluation
In JavaFX, attribute initializers can be specified to be lazily and/or incrementally evaluated with the bind operator. Attributes initialized with bind are akin to cells in a spreadsheet that contain formulas rather than literal values. During the lifetime of the object containg the attribute, whenever any of the objects referenced by the right hand side of the initializer expression changes the left hand side (the attribute's value) is automatically updated. Here is an example:

         import java.lang.System;

         class X {
               attribute a: Number;
               attribute b: Number;
               attribute c: Number;
         }

         trigger on X.b = newValue {
               System.out.println("X.b is now {newValue}";
         }

         trigger on X.c = newValue {
               System.out.println("X.c is now {newValue}";
         }

         var x1 = X {
              a: 1
              b: 2   // X.b is now 2 is printed
              c: 3   // X.c is now 3 is printed
         };

         var x2 = X {
              a:  x1.a       // eager, non-incremental
              b:  bind x1.b // eager, incremental (X.b is now 2 is printed)
              c:  bind lazy x1.c  // lazy, incremental (nothing is printed yet)
         };

        System.out.println(x2.a); // prints 1
        System.out.println(x2.b); // prints 2
        System.out.println(x2.c); // prints X.c is now 3, then prints 3

        x1.a = 5;
        x1.b = 5; // prints X.b is now 5, twice
        x1.c = 5; // prints X.c is now 5, twice

        System.out.println(x2.a); // prints 1
        System.out.println(x2.b); // prints 5
        System.out.println(x2.c); // prints 5
         In the above example, the b and c attributes of x2 are bound to the b and c attributes of x1. This means that whenever x1's b or c attribute is updated the b and c attributes of x2 will be correspondingly updated. The difference between x2.b and x2.c is that the former's value is immediately updated in its attribute initializer whereas the latter's binding is not evaluated until its value is accessed the first time.

Note: the body of a function is always incrementally evaluated without requiring the bind operator, however the body of an operation is not. Unlike a function, inside an operation changes to local variables do not trigger incremental evaluation. Incremental evaluation is not performed inside the body of an operation except for expressions explicitly prefixed by bind.

Nevertheless when you call an operation (or a Java method) from an incremental evaluation context the call itself is incrementally evaluated. This means that if the values of any of the arguments to the call change a new fresh call to that operation or method will be made and a new value returned.

By contrast, function's are only called once and the result of the evaluation is incorporated into the callers evaluation tree.

Incremental evaluation is one of JavaFX's main distinguishing features that makes it possible to define complex dynamic GUI's declaratively. The lazy evaluation feature is needed to handle recursive data structures like trees and graphs.

top

Reflection
JavaFX classes, attributes, and operations are reflected as follows:

        public class Class {
            public attribute Name: String;
            public attribute Documentation:String?;
            public attribute Superclasses: Class* inverse Class.Subclasses;
            public attribute Subclasses: Class* inverse Class.Superclasses;
            public attribute Attributes: Attribute* inverse Attribute.Scope;
            public attribute Operations: Operation* inverse Operation.Target;
            public function instantiate();
        }

        public class Operation extends Class {
            public attribute Target: Class? inverse Class.Operations;
        }

        public class Attribute {
            public attribute Name: String;
            public attribute Documentation: String?;
            public attribute Scope: Class? inverse Class.Attributes;
            public attribute Type: Class?;
            public attribute Inverse: Attribute* inverse Attribute.Inverse;
            public attribute OneToOne: Boolean;
            public attribute ManyToOne: Boolean;
            public attribute OneToMany: Boolean;
            public attribute ManyToMany: Boolean;
            public attribute Optional: Boolean;
        }
JavaFX supports reflective access to classes, attributes, and member functions and operations, through the class operator, for example:

        import java.lang.System;

        System.out.println(1.class.Name) // prints "Number"
        System.out.println("Hello".class.Name); // prints "String"

        class X {
            attribute a: Number;
        }
        var x = new X();
        System.out.println(x.class.Name); // prints "X"
        System.out.println(sizeof x.class.Attributes); // prints 1
        System.out.println(x.class.Attributes[0].Name); // prints "a"Reflective access to the value of an attribute is provided by the [] operator when its operand is of type Attribute, for example

        import java.lang.System;

        class X {
            attribute a: Number;
        }
        var x = new X();
        x.a = 2;
        System.out.println(x[x.class.Attributes[Name == 'a']]); // prints 2
        // the above statement is equivalent to this non-reflective code:
        System.out.println(x.a);
In JavaFX, the member functions and operations of a class are themselves modeled as classes in which the target class, formal parameters, and return value are represented as attributes. The name of the attribute representing the target object is 'this'. The name of the attribute representing the return value is 'return'. The attributes representing the formal parameters have the same names as the formal parameters.

You obtain such reflected operations from the Class object.

Reflected JavaFX operations can be called like functions by passing the target object as the first argument and any parameters as subsequent arguments, e.g:

        import java.lang.System;

        class X {
            operation foo(n: Number): Number;
        }

        var x = new X();
        var op = x.class.Operations[Name == 'foo'];
        System.out.println(op(x, 100));

        // the above code is equivalent to the following non-reflective code:
        System.out.println(x.foo(100));

Currently, the bean properties and public fields of Java classes are reflected as JavaFX attributes. However, Java methods are not reflected as JavaFX operations. If you want to call a Java method reflectively you can simply use the normal Java API's.

Note that, unlike Java, in JavaFX the class operator is applied to an expression rather than to a type name. JavaFX supports the following syntax to obtain the reflected class object from a type name:

           :TypeName
For example:

           import java.lang.System;
           System.out.println(:System.Name); // prints "java.lang.System"
           System.out.println(:System.class.Name); // prints "Class"
top

Extents and Enumerations
In JavaFX, the extent of a class, i.e. the set of all instances of that class, can be obtained with the following syntax:

              *:ClassName
For example, the following code prints out all instances of class String.

              import java.lang.System;

              for (i in *:String) {
                  System.out.println(i);
              }
Note: this is an optional feature and is disabled by default.

JavaFX also provides the capability to declare named instances of a class with the following syntax:               objectName:ClassName
For example:

              import java.lang.System;

              myString:String = "This is a string";

              System.out.println(myString:String);
Such named instances are globally accessible but must normally be qualified with the class name. However, In the context of attribute initializers and assignments the named instances of the expression's type are introduced into the lexical scope (with weaker visibility than variables and attributes) and may be referenced with their unqualified names, for example:

              Button {
                  mnemonic: P
                  text: "Press Me"
              }In the above example, since the mnemonic attribute of Button is of type KeyStroke, I can access the named value P with its unqualified name (elsewhere I would have to refer to it as P:KeyStroke).

The values of Java 1.5 enumerated types may be accessed with the same syntax, for example:

              import java.lang.management.MemoryType;

              var heap = HEAP:MemoryType;
              var nonHeap = NON_HEAP:MemoryType;


只看该作者    顶部
 
    

相关内容


CopyRight 1999-2006 itpub.net All Right Reserved.
北京皓辰广域网络信息技术有限公司. 版权所有
E-mail:Webmaster@itpub.net
京ICP证:010037号 联系我们 法律顾问