JavaFX Scriptプログラム言語を学ぼう

レッスン9:クラスを書く

JavaFX Scriptプログラム言語のAPIは、あなたのアプリケーションにすぐ使えるように用意されている たくさんのクラスを含んでいます。 しかし、ある時点で、アプリケーション固有のあなた自身のクラスを書くことが道理にかなうということに たぶん気付くでしょう。このレッスンはそれに必要な上位レベルの入門です。 下位レベルの考察については JavaFXプログラム言語リファレンス5章. クラスをご覧ください。

Customerクラスの例


オブジェクトを使う」で、あなたはオブジェクトの使い方を学びました。 私達は必要なAddress.fxとCustomer.fxを準備したことを思い出したください。 これらのソースファイルはクラス定義を含んでいましたが、私達はその内容についてまったく触れませんでした。 このセクションはあの例を再び訪れ、今度は、同ファイルにあなたが必要とするすべてのものを配置します。

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}");
    }
}

この例は、あなたが変数と関数についてすでに知っていることをベースにしたおなじみのものに見えるはずです。 Addressクラスはstreet, city, state, zipのインスタンス変数をString型で宣言しています。 Customerクラスも同様にいくつかのインスタンス変数を宣言していて、 さらにその値を印字する関数もあります。 これらの変数と関数はクラスの中で宣言されているので、あなたが作るあらゆるAddressとCustomerオブジェクトが 利用可能です。

他のクラスを継承する


あなたは他のクラスから変数と関数を継承するクラスを書くこともできます。 例えば、銀行口座への預金と引き出しをイメージしてください。 どちらも口座番号と残高を持っています。あなたは残高を問い合わせ、預金をし、引き出しをします。 私達はとても一般的な変数と関数を提供する土台となるAccountクラスを作ることで、これをモデル化できます。

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;
     }
}

私達はこのクラスをabstractとしました。これはAccountオブジェクトが直接生成できないことを意味します。 (この設計の意図はあなたが預金と引き出しだけを生成できることです。)

accountNumとbalance変数は、口座番号と現在の残高を保持しています。 残りの関数は基本的な動作を提供するもので、それは残高を得ること、預金すること、引き出すこと、です。

私達はSavingAccountクラスを定義しました。 これは、これらの変数と関数を継承するためにextendsキーワードを使います。

class SavingsAccount extends Account {

     var minBalance = 100.00;
     var penalty = 5.00;

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

SavingAccountはAccountのサブクラスなので、自動的にAccountのインスタンス変数と関数の全てを含みます。 これはSavingAccnountのソースコードを、それが親クラスとどう違うのかについて存分に注目させます。 (その違いとは、預金がペナルティを避けるために最低の残高を100ドルに維持しなければならないという要求です。)

私達は同様にCheckingAccnoutクラスを定義でき、これも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!
          }
     }
}

これがAccountと違うのは、残高を超えた引き出しの防御を口座が持っているかどうかを探知する変数を 定義していることです。(もし、チェックに書いたように引き出しが結果として残高をマイナスにしたら、 その防御が動いて、小切手が不渡りになることを保証します。) このケースでは、私達は継承したwithdraw関数の振る舞いを変更していることに注意してください。 これは関数のオーバーライドとして知られていて、overrideキーワードで示されます。

Mixin継承の使い方


上で登場したAccount, SavingAccount, CheckingAccountクラスは、単一継承の例です。 いくつかのプログラム言語は多重継承をサポートしていて、 これは任意のクラスが複数のクラスを直接継承できることを意味します。 JavaFXプログラム言語は多重継承をサポートしていません。 その代わりにmixin継承をサポートしていて、 多くの同じ恩恵を提供していますが、結果的に生成されたコードを単純で小さく高速にします。

mixinは特別な種類のクラスです。 それは直接インスタンス化できませんが、むしろ拡張されてサブクラスから使われるようにデザインされています。 mixinは通常のクラスのようですが、その宣言にmixinキーワードを持っています。 通常のクラスと同様に、mixinクラスはあらゆる変数や関数を定義できます。

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 { }

この例では、myMixeeオブジェクトのprintName関数が実行されると、 コンソールに継承した名前の"John Doe"が印字されます。 この振る舞いを変えるには、通常のクラスから継承するときとまったく同じように、 あなたはMyMixeeクラスのprintNameをオーバーライドします。 しかし、通常のクラスと違うのは、mixin継承は複数のmixinクラスの拡張ができるということで、 あなたに多重継承の恩恵の多くを与えます。

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 { }

この例は二つのクラス(MyNameMixinとMyAddressMixin)と その両方を拡張した通常のクラス(MyContact)を定義しています。 オブジェクト指向のソフトウェア設計の全般的な議論はこのチュートリアルの範囲を超えています。 (例えばmixin継承を使うときと使わないときの決め手) しかし、基本的なルールの「何が許されて、何がそうでないか」は簡単に書けます。

ルール:

  1. JavaFXクラスは多くとも一つのJavaFXクラスを拡張ができます。 JavaFXプログラム言語はJavaプラットホームの上に成り立っているので、 このスーパークラスもJavaで書かれていて、あなたのコードは正常にコンパイルと実行ができるのです。
  2. JavaFXクラスはJavaFXのmixinクラスをいくつでも拡張できます。 (あなたがJavaプログラマなら、JavaFXクラスが同様にいくつものJavaインターフェースを拡張できる ことも知っているでしょう。)
  3. JavaFXのmixinクラスは他のmixinクラスをいくつでも拡張できます。上の2.のように mixinクラスはJavaインターフェースをいくつでも拡張することもできます。

Home