連載
Javaオブジェクトモデリング
第5回
静的モデル:データ型におけるUMLとJavaのマッピング(1)
浅海智晴
2002/10/1
■■3.4 バリューオブジェクトの導入■■
それでは、“データ型”として利用できるオブジェクトとは、どのようなものでしょうか。もちろんこれは「値」として扱うことができるということです。「値を表現するためのオブジェクト」は、値を扱う場合と同じ使い勝手を提供することが必要です。このような性質を持つオブジェクトを本連載では「バリューオブジェクト」と呼ぶことにします。バリューオブジェクトであるためには、以下の要件を満たすことが必要となります。
- 変数への代入に特別な配慮がいらないこと
- 内容による比較ができること
大事なところなので、ちょっと細かく見ていきます。
●3.4.1 変数の更新(プリミティブ型)
Javaにおいて、オブジェクトを格納する変数は、正確にはオブジェクトへの参照を格納しています。「変数への代入に特別な配慮がいらないこと」とは、オブジェクトへの参照をそのまま代入しても、矛盾が起こらないということです。例を使って説明しましょう。リスト1のSpaceShipは、2次元座標上での場所のデータをインスタンス変数x、yに格納しています。SpaceShipの移動はmoveメソッドを使って行います。moveメソッドは、引数で渡された値をそのままインスタンス変数に代入しています。また、SpaceShipの現在位置はprintメソッドでコンソールに表示することができます。
リスト1 SpaceShip.java |
public class SpaceShip { public
void print() { |
テストのためのプログラムClientで、SpaceShipの動作を確認します(リスト2)。Clientはmoveメソッドを用いてSpaceShipを移動させた後、SpaceShipの場所をコンソールに表示させています。プログラムで少し変わっているところは、SpaceShipの移動後、SpaceShipの移動に用いた変数xと変数yの内容を更新している点です。
リスト2 Client.java |
public class Client { |
Clientの動作は以下のようになります(実行結果1)。
実行結果1 |
$ java Client |
当たり前ですが、SpaceShipのmoveメソッドを呼んだ後で、変数の値を変えてもSpaceShipには影響を与えません。
●3.4.2 変数の更新(オブジェクト)
次はSpaceShipの位置をプリミティブ型ではなく、2次元座標上の位置を表現するオブジェクトPoint(リスト3)を使って実現します。
リスト3 Point.java |
public class Point { |
Point版のSpaceShipは、リスト4となります。moveメソッドは、引数で渡された値をそのままインスタンス変数に代入しています。
リスト4 SpaceShip.java(Point版) |
public class SpaceShip { public void move(Point position)
{ |
テストのためのプログラムClientはリスト5となります。moveメソッドの呼び出し前に、オブジェクトに値を設定。moveメソッドの呼び出しの後に、オブジェクトの値を更新しています。
リスト5 Client.java |
public class Client { |
Clientの動作は以下のようになります(実行結果2)。
実行結果2 |
$ java Client |
今度は、このように値が変わってしまいました。本来は“x = 100、y = 200”となるのが想定された動作ですが、残念ながら“x = 200、y = 300”という結果となってしまいました。このように、データをプリミティブ型の変数を用いて処理しているときには発生しなかった問題が、オブジェクトを使うと発生してきます。
●3.4.3 データの比較(プリミティブ型)
もう1つの問題は、データの比較です。まずプリミティブ型のデータの場合を見てみましょう。今度のSpaceShipはリスト6となります。isHitメソッドによって、現在の位置が、指定された座標にヒットしているかを調べることができます。
リスト6 SpaceShip.java |
public class SpaceShip { public void move(int x, int
y) { public boolean isHit(int x,
int y) { |
この場合の、isHitメソッドの実装は値をそのまま比較すればよいだけです。動作確認のためのプログラムはリスト7となります。
リスト7 Client.java |
public class Client { |
それでは、実行してみましょう(実行結果3)。
実行結果3 |
$ java Client |
当然ですが、無事動作しました。
●3.4.4 データの比較(オブジェクト)
次は、オブジェクトを使った場合です。オブジェクトPointは先ほど使ったものと同じです(リスト8)。
リスト8 Point.java |
public class Point { |
SpaceShipは、位置データの格納にオブジェクトPointを使うように変更されています(リスト9)。
リスト9 SpaceShip.java |
public class SpaceShip { public void move(Point position)
{ public boolean isHit(Point
position) { |
動作確認のためのプログラムはリスト10となります。 変数point1と変数point2は、いずれもオブジェクトPoint型の変数です。まず変数point1に値を設定し、これを用いてSpaceShipのmoveメソッドを呼び出しています。次に変数point1に、変数point2に設定したものと同じ値を設定し、これを用いてSpaceShipのisHitメソッドを呼び出します。
リスト10 Client.java |
public class Client { |
それでは実行してみましょう(実行結果4)。
実行結果4 |
$ java Client |
今度の結果は期待どおりにはなりませんでした。本来はtrueになってほしいところですが、falseが表示されました。同じ内容を持つデータを比較したのにもかかわらず、比較の実行結果は“同じではない”となったわけです。
以上、今回はJavaにおけるデータ型の扱いについて説明しました。UMLのデータ型をそのままJavaの世界に持ってくるとクラス図が繁雑になってしまうという問題があります。この問題を解決するために“データ型”という概念を導入しました。
次回は、“データ型”を軸にJavaによるデータ型の実装の戦略、実装例を解説していきます。
2/2
|
Javaオブジェクトモデリング 第5回 | |
オブジェクトとデータ | |
バリューオブジェクトの導入 |
Javaオブジェクトモデリング INDEX |
IT Architect 連載記事一覧 |