前回「オブジェクト指向、本当に分かってる?」では、Javaを学習するうえで避けては通れない概念、「オブジェクト指向」について解説しました。開発にオブジェクト指向を採用するメリットが垣間見られたと思います。
最後にはJavaの言語仕様を用い、自動販売機オブジェクトとその利用者との関係をシミュレートしました。
前回までの流れを図で確認します(図1)。
クラスを抽象的に定義することによって、性質の異なる類似のオブジェクト(ジュースの自動販売機、タバコの自動販売機など)を効率よく生成できることが、オブジェクト指向のメリットの1つであると紹介しました。
前回、実際にUser1(利用者1)クラスとVending(自動販売機)クラスを実行してオブジェクトを生成することができたと思います。「オブジェクトを生成する」といっても目に見えるものではなく、オブジェクトの機能がメモリ上に展開されているということになります。
オブジェクトを生成すると、そのオブジェクトの「操作」を利用することができます。自動販売機オブジェクトの操作は「支払金を受け取る」「商品を出す」「おつりを算出する」になります。
1 //User1(利用者1)クラスの定義 2 class User1{ 3 //mainメソッド(プログラムを開始する機能)の定義 4 public static void main(String[] args){ 5 //Vending(自動販売機)オブジェクトを作成 6 Vending drink = new Vending("Coffee", 130); 7 } 8 }
User1クラスの6行目の処理「Vending drink = new Vending("Coffee", 130);」を見てみると、インスタンス化を行う「new Vending("Coffee", 130);」の左側に「Vending drink =」があります。
「=」は、ほかのプログラム言語でも用いられる代入演算子です。「Vending drink」は、Vendingクラス型の変数「drink」を宣言していることになります。
この処理は「newキーワードによってVendingクラスから生成されたオブジェクトを、Vendingクラス型の変数drinkで参照する」という意味になります(図2)。
Javaにおける「参照」の仕組みは、Javaの言語仕様を理解するうえで非常に重要です。本稿以外の資料(書籍やWebサイトなど)も参考にして、十分に学習することをお勧めします。
生成したオブジェクトを参照した状態になっていれば、そのオブジェクトの操作を自由に呼び出して利用することが可能です。
Vendingクラスのソースコード[Vending.java]を確認しましょう(クリックで拡大します)。
Vendingクラスの中には、これまで解説していなかった操作が3つあると思います。前回解説したとおり、Javaの言語仕様では操作をメソッドで実装します。
操作に関して、簡単に解説します。
18〜21行目に定義されているのは、setPaymentメソッド(支払設定機能)です。18行目のメソッド宣言文では、setPaymentメソッドの利用者が支払い金額として( )内に設定する値を整数(int)の「p」として扱い、操作の処理結果として利用者に返す値(戻り値)は何もない(void)ということを表しています。
setPaymentメソッドが利用者から呼び出されたときに実行される処理内容として、19行目には利用者が設定した整数値である「p」を属性の「payment」に設定する処理が、20行目には属性に整数値を設定したことを確認する出力処理が、それぞれ書かれています。
23〜25行目に定義されているのは、getGoodsメソッド(商品取得機能)です。23行目のメソッド宣言文では、getGoodsメソッドの利用者が( )内に設定する値はなく、操作の処理結果として利用者に返す値(戻り値)は文字列(String)であるということを表しています。
getGoodsメソッドが利用者から呼び出されたときに実行される処理内容として、24行目には属性「goods」の値を利用者に返す(return)という処理が書かれています。
27〜29行目に定義されているのは、getChangeメソッド(おつり取得機能)です。27行目のメソッド宣言文では、getChangeメソッドの利用者が( )内に設定する値はなく、操作の処理結果として利用者に返す値(戻り値)は整数(int)であるということを表しています。
getChangeメソッドが利用者から呼び出されたときに実行される処理内容として、28行目では属性「payment」の値と属性「price」の値の減算の結果を利用者に返す(return)という処理が書かれています。
以上の操作は、ソースコード上に記述されている順番とは関係なく、利用者から呼び出されたときにその処理内容を実行することになります。
ではこれからUser1クラスを修正し、これらの操作を呼び出していこうと思います。皆さんの頭の中では、「自動販売機を設計図から組み立てて、これから缶コーヒーを買おうとしている」という状況をイメージしておいてください。
User1クラスを修正し、操作の呼び出しを新たに追加したUser2クラスを以下に示します(クリックで拡大します)。ソースファイルがダウンロードできます。
6行目までの内容は、User1クラスとまったく同じです。
User2がjavaコマンドによって実行されるとmainメソッド内の処理が実行され、6行目の処理が実行されたところでVendingクラスからVendingオブジェクトが生成されます。前回の解説を確認しておいてください。
生成されたオブジェクトは、mainメソッド内の処理が終了するまで(15行目の処理が終わるまで)は「drink」という変数で参照されているので、「drink.操作名( )」という形でオブジェクトの操作を呼び出すことができます(図3)。
9行目は、setPaymentメソッド(支払設定機能)の呼び出しです。( )内に指定した値「200」は属性の「payment」に設定されます。これは「料金を自動販売機に投入した」ということですね。
12行目は、getGoodsメソッド(商品取得機能)の呼び出しです。呼び出すと、Vendingオブジェクトを生成した際に設定している属性「goods」の値「"Coffee"」を返してきます。実際に戻ってくる値は「商品名」の文字列ですが、これはつまり「商品を購入した」ことに相当します。
15行目は、getChangeメソッド(おつり取得機能)の呼び出しです。呼び出すと、すでにsetPaymentメソッドで設定している属性「payment」の値「200」とVendingオブジェクトを生成した際に設定している属性「price」の値「130」との引き算の結果「70」を返してきます。これは「おつりを受け取っている」ということです。
getGoodsメソッドとgetChangeメソッドは戻り値(return)がある操作です。ソースコード中では出力処理「System.out.println()」の( )内にその呼び出しが記述されているので、戻り値がそのまま用意した文字列と結合されて画面上に出力されることになります。
[User2.java]と[Vending.java]をコンパイルして[User2.class]を実行すると、以下のようにコマンドプロンプトに出力されるはずです。
Vending was constructed! Goods: Coffee Price: 130 yen 200 yen was received. You bought a Coffee. Change: 70 yen
いかがですか。自動販売機を組み立て、商品を購入することができたでしょうか。
分析からコーディングまでの流れは、自然言語(例えば日本語)を「Java語」に置き換える翻訳作業を行っているようにも見えますね。
Copyright © ITmedia, Inc. All Rights Reserved.