Sun Java Solaris Communities My SDN Account Join SDN

Learning the JavaFX Script Programming Language - Tutorial Overview

Lesson 9: Writing Your Own Classes

   
« Previous 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Next »
 
The JavaFX Script programming language API contains a number of classes ready for immediate use in your applications. However, at some point, you will probably find that it makes sense to write some application-specific classes of your own. This lesson provides a high-level introduction to what that entails. For a lower-level discussion, see Chapter 5. Classes in the JavaFX Script Programming Language Reference.
 
Contents
 
The Customer Example
Inheriting from Other Classes
Using Mixin Inheritance
 
The Customer Example

In Using Objects, you learned how to use objects. Recall, however, that we provided the necessary Address.fx and Customer.fx files. These source files contained class definitions, but we didn't discuss their contents at all. This section re-visits that example, this time placing everything you'll need into the same file:

def customer = Customer {
     firstName: "John";
     lastName: "Doe";
     phoneNum: "(408) 555-1212"
     address: Address {
          street: "1 Main Street";
          city: "Santa Clara";
          state: "CA";
          zip: "95050";
     }
}

customer.printName();
customer.printPhoneNum();
customer.printAddress();

class Address {
     var street: String;
     var city: String;
     var state: String;
     var zip: String;
}

class Customer {
     var firstName: String;
     var lastName: String;
     var phoneNum: String;
     var address: Address;

    function printName() {
        println("Name: {firstName} {lastName}");
    }

    function printPhoneNum(){
        println("Phone: {phoneNum}");
    }

    function printAddress(){
        println("Street: {address.street}");
        println("City: {address.city}");
        println("State: {address.state}");
        println("Zip: {address.zip}");
    }
}
 

This example should look familiar based on what you already know about variables and functions. The Address class declares street, city, state, and zip instance variables all of type String. The Customer class declares a few instance variables as well, plus functions to print out their values. Because these variables and functions are declared within classes, they will be available to any Address and Customer objects that you create.

Inheriting from Other Classes

You can also write classes that inherit variables and functions from other classes. For example, imagine a savings and checking account at a bank. Each has an account number and a balance. You can query the balance, make deposits, or make withdrawals. We can model this by creating a base Account class that provides the most common variables and functions:

abstract class Account {

     var accountNum: Integer;
     var balance: Number;

     function getBalance(): Number {
          return balance;
     }

     function deposit(amount: Number): Void {
          balance += amount;
     }

     function withdraw(amount: Number): Void {
          balance -= amount;
     }
}
 

We have marked this class as abstract, meaning that Account objects cannot be created directly (the intent of this design is that you may only create savings accounts or checking accounts.)

The accountNum and balance variables hold the account number and current balance. The remaining functions provide the basic behavior for getting the balance, making a deposit, or making a withdrawal.

We can then define a SavingsAccount class that uses the extends keyword to inherit these variables and functions:

class SavingsAccount extends Account {

     var minBalance = 100.00;
     var penalty = 5.00;

     function checkMinBalance() : Void {
          if(balance < minBalance){
               balance -= penalty;
          }
     }
}
 

Because SavingsAccount is a subclass of Account, it will automatically contain all of Account's instance variables and functions. This leaves the SavingsAccount source code free to focus on how it differs from that of its parent (a requirement that the savings account holder must maintain a minimum balance of $100 to avoid a penalty.)

We can similarly define a CheckingAccount class that also extends Account:

class CheckingAccount extends Account {

     var hasOverDraftProtection: Boolean;

     override function withdraw(amount: Number) : Void {
          if(balance-amount<0 and hasOverDraftProtection){

               // code to borrow money from an overdraft account would go here

          } else {
               balance -= amount; // may result in negative account balance!
          }
     }
}
 

This differs from Account by defining a variable that tracks whether or not the account holder has overdraft protection (if a withdrawal — such as writing a check — would result in the balance becoming less than zero, overdraft protection would activate to ensure that the check does not bounce). Note that in this case we are changing the behavior of the inherited withdraw function. This is known as function overriding, as indicated by the override keyword.

Using Mixin Inheritance

The Account, SavingsAccount, and CheckingAccount classes listed above are all examples of single inheritance. Some programming languages support multiple inheritance, meaning that a given class can directly extend any number of other classes. The JavaFX Script programming language does not support multiple inheritance; it instead supports mixin inheritance, which provides many of the same benefits, but results in simpler, smaller, and faster generated code.

A mixin is a special kind of class. It is one that cannot be instantiated directly, but rather, is designed to be extended and then used by its subclasses. Mixins look like regular classes, but have the mixin keyword included in their declaration. As with regular classes, mixin classes may define any number of variables or functions:

def  myMixee = MyMixee{};
myMixee.printName();

mixin class MyMixin {
     var firstName = "John";
     var lastName = "Doe";
     function printName(){
          println("My name is: {firstName} {lastName}");
     }
}

class MyMixee extends MyMixin { }
 

In this example, the inherited name "John Doe" is printed to the screen when the printName function is invoked on the myMixee object. To change this behavior, you would override printName in the MyMixee class, just like you would when inheriting from a regular class. But unlike with regular classes, mixin inheritance allows you to extend multiple mixin classes, giving you many of the benefits of multiple inheritance:

def myContact = MyContact{};
myContact.printName();
myContact.printAddress();

mixin class MyNameMixin {
     var firstName = "John";
     var lastName = "Doe";
     function printName(){
          println("My name is: {firstName} {lastName}");
     }
}
mixin class MyAddressMixin {
     var address = "1 Main Street, Anytown USA";
     function printAddress(){
          println("My address is: {address}");
     }
}

class MyContact extends MyNameMixin, MyAddressMixin { }
 

This example defines two mixin classes (MyNameMixin and MyAddressMixin), then a regular class (MyContact) that extends them both. A full discussion of object-oriented software design (i.e. deciding when to use mixin inheritance and when not to) is beyond the scope of this tutorial, but the basic rules of what is allowed and what is not are straightforward to describe.

These rules are:

  1. JavaFX classes are allowed to extend, at most, one other JavaFX class. Because the JavaFX Script programming language is based on the Java platform, this superclass also could be written in Java and your code would still compile and run correctly.

  2. JavaFX classes are allowed to extend any number of JavaFX mixin classes. (If you are a Java programmer, know that JavaFX classes can also extend any number of Java interfaces as well.)

  3. JavaFX mixin classes are allowed to extend any number of other JavaFX mixin classes. As with #2 above, JavaFX mixin classes may also extend any number of Java interfaces.
 
« Previous 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Next »
 
 
Rate This Article
 
Comments
Do you have comments about this article? We welcome your participation in our community. Please keep your comments civil and on point. You may optionally provide your email address to be notified of replies - your information is not used for any other purpose. By submitting a comment, you agree to these Terms of Use.

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.