第 12 回 汎用的なリストと JavaAPI
~クラスの再利用について考えよ
う~
学習目標
クラスの再利用について議論できる
汎用的なクラスとはどういうものか説明できる
汎用的なクラスを作るために、効果的に継承を利用す ることを議論できる
継承と委譲による設計の違いをクラスの再利用という 側面から説明できる
簡単なコレクション JavaAPI を利用したプログ ラムが書ける
クラスのキャストを正しく使ったプログラムが書ける
Object
型の存在を説明できる12.1 汎用的なリスト
12.1.1 今回考える題材
12.1.2 再利用を考える
12.1.3 汎用的なリストの実装
12.1.4 キャスト
12.1.1 今回考える題材
リストによる1対多の実装
商品種類と商品種類リスト
商品種類
-
商品番号-
商品名-
価格商品種類リスト
+
追加( )
+
削除( ) +
検索( ) +
表示( )
0. . n 1 1
0. . n
今回考える題材
リストによる 1 対多の実装はよくある ケース
今回は、金の種類も扱う時を考える
構造は同じ
金種類 - 価値
金種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( )
0. . n 11
0. . n
商品種類
- 商品番号
- 商品名
- 価格
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( ) 1
0. . n 1
0. . n
12.1.2 再利用を考える
金種類リストと商品種類リストはほと んど同じコードが書かれている
// 金種類リストクラス
public class MoneyTypeList {
private int ARRAY_SIZE = 20;
private MoneyType[] moneyTypeArray;
private int size = 0;
// コンストラクタ
public MoneyTypeList() {
moneyTypeArray = new MoneyType[ARRAY_SIZE];
}
// リストに金種類を追加する
public void add(MoneyType newMoneyType){
moneyTypeArray[size] = newMoneyType;
size++;
}
// 商品種類リストクラス
public class ItemTypeList { private int ARRAY_SIZE = 20;
private ItemType[] itemTypeArray;
private int size = 0;
// コンストラクタ
public ItemTypeList() { itemTypeArray = new ItemType[ARRAY_SIZE];
}
// リストに商品種類を追加する public void add(ItemType newItemType){
itemTypeArray[size] =
例題12-1
(MoneyTypeList.java) 例題 12-1
(ItemTypeList.java)
再利用をできるように
共通部分、異なる部分を挙げてみよう
// 金種類リストクラス
public class MoneyTypeList {
private int ARRAY_SIZE = 20;
private MoneyType[] moneyTypeArray;
private int size = 0;
// コンストラクタ
public MoneyTypeList() {
moneyTypeArray = new MoneyType[ARRAY_SIZE];
}
// リストに金種類を追加する
public void add(MoneyType newMoneyType){
moneyTypeArray[size] = newMoneyType;
size++;
}
// 商品種類リストクラス
public class ItemTypeList { private int ARRAY_SIZE = 20;
private ItemType[] itemTypeArray;
private int size = 0;
// コンストラクタ
public ItemTypeList() { itemTypeArray = new ItemType[ARRAY_SIZE];
}
// リストに商品種類を追加する public void add(ItemType newItemType){
itemTypeArray[size] =
配列の型
引数
① 問題の分析
プログラムが共通の点
追加、削除のアルゴリズム
プログラムが異なる点
取り扱う配列の型が違う
取り扱う引数の型が違う
アルゴリズムの意味は同 じ
取り扱う要素の型が違う
ことが問題
問題の分析
型が違う→意味が違う
どう違うのか
商品種類リストに商品種類を追加する
金種類リストに金種類を追加する
可読性(意味が明確)をすこし犠牲に して、再利用性を高める
リストに「要素」を追加する
要素の型が違うことが問題
型を同じにするためには
継承を使うことによって、「プログラムの 意味」をに注目した「リスト」という語彙 ができた
商品種類配列リスト 商品種類連結リスト Mai n
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( )
リストの立場から考える
汎用的なリストにとっての意味を考え る
金種類 - 価値
汎用リスト + 追加( ) + 削除( ) 商品種類
- 商品番号
- 商品名
- 価格
共通の意味
商品種類も金種類もリストから見れば
、同じ「要素」という意味がある
継承を利用し「要素」という語彙を作る
金種類
- 価値 商品種類
- 商品番号
- 商品名
- 価格
リスト要素 汎用リスト
+ 追加( ) + 削除( )
12.1.3 汎用的なリストの実装
① Object 型を利用する
ここでは、 List 要素クラスとして Object 型を考える
金種類
- 価値 商品種類
- 商品番号
- 商品名
- 価格
Obj ect 汎用リスト
+ 追加( ) + 削除( )
何故 Object 型を使うのか
Java では「すべてのクラスは自動的に
Object クラスを継承する」決まりに
なっている
extends と書かなくても自動的に Object 型 を継承する
List 要素クラスを定義して、継承する必要がなく、
すべてのオブジェクトを格納できる List になる
② 汎用的な List のリスト
// 汎用リストクラス
public class ObjectList {
private int ARRAY_SIZE = 20; // 配列の大きさ
private Object[] objectArray; //Object を保存する配列 private int size; // 要素数
// コンストラクタ
public ObjectList() {
objectArray = new Object[ARRAY_SIZE];// 配列を初期化する }
// リストにObject を追加する
public void add(Object newObject){
objectArray[size] = newObject;
size++;
}
例題 12-2 (ObjectList.java)
汎用的な List の利用
例題 12-2
今までの共通部分を
まとめた汎用リストクラス
金種類 - 価値
商品種類
- 商品番号
- 商品名 - 価格
金種類リスト + 追加( )
+ 削除( ) + 検索( )
+ 表示( ) 汎用リスト + 追加( ) + 削除( ) 商品種類リスト
+ 追加( ) + 削除( ) + 検索( ) + 表示( ) 0. . n
0. . n
1 1 0. . n
1 1 0. . n
Obj ectクラス を省略
重複コードがなくなる
// 商品種類リストクラス
public class ItemTypeList {
private ObjectList itemTypeList;
// コンストラクタ
public ItemTypeList() {
itemTypeList = new ObjectList();
}
// リストに商品種類を追加する
public void add(ItemType newItemType){
itemTypeList.add(newItemType);
}
// 金種類リストクラス
public class MoneyTypeList {
private ObjectList moneyTypeList;
// コンストラクタ
public MoneyTypeList() {
moneyTypeList = new ObjectList();
}
// リストに金種類を追加する
public void add(MoneyType newMoneyType){
moneyTypeList.add(newMoneyType);
} 例題12-2
(MoneyTypeList.java) 例題 12-2
(ItemTypeList.java)
12.1.4 キャスト
① 検索に対応する
② 型変換 ( キャスト )
① 検索に対応する
汎用リストでは検索や表示ができない
理由を考えてみよう
検索や表示が
汎用化できない理由
① 検索に対応する
検索に対応するためにリストにアクセ スするメソッドを追加する
size()
get(int index)
検索対応メソッド
// 汎用リストクラス
public class ObjectList {
private int ARRAY_SIZE = 20; //配列の大きさ
private Object[] objectArray; //Objectを保存する配列 private int size; //要素数
// コンストラクタ
public ObjectList() {
objectArray = new Object[ARRAY_SIZE];//配列を初期化する }
// 途中省略
// リストの要素数を取得する public int size(){
return size;
}
//index番目の要素を得る
public Object get(int index){
例題 12-2 (ObjectList.java)
② 型変換 ( キャスト )
//ItemTypeList より抜粋
// 指定された商品番号を持つ商品種類を検索する
public ItemType search(int searchID){
int len = itemTypeList.size(); //
リストの大きさ for(int i=0;i<len;i++){ItemType itemType = (ItemType)itemTypeList.get(i);//i
番目の要素取得 if(itemType.getId() == searchID){//id を比較return itemType;//
見つかった }}
// 見つからなかった return null;
}
ここに注目!
例題 11-2
(ItemTypeList.java)
型変換 ( キャスト )
ItemType itemType = (ItemType)itemTypeList.get(i);
取得した i 番目の要素は Object 型
汎用リストは要素を Object 型で扱う
欲しい要素は ItemType 型
Object 型として扱われているが実際は ItemType 型
型変換(キャスト)が必要
クラス・キャスト
オブジェクトの見え方を変換する
実際のオブジェクトは変わらないことに注意
型変換をする条件
変換するクラスが継承関係にあること
もちろんそのクラスのインスタンスでなければダメ
Object 型として見る このオブジェクトに
対して ItemType 型として見る
I t emType - i d
- name Obj ect
コーラ:ItemType
id=1001
name=コーラ
price=120円
自動キャスト
下記の追加メソッドは何故うまくいく
// リストに商品種類を追加する
か
public void add(ItemType newItemType){
itemTypeList.add(newItemType);
}
// リストに商品種類を追加する
public void add(ItemType newItemType){
itemTypeList.add()
の引数 にはObject
型が必要では?
もちろん、このようにプログラム
ItemType→ Object のキャストは自動的に行われるためうまくいく
キャスト まとめ
自動的キャストと明示的キャスト
サブクラス→スーパークラスの変換は自動 的にキャストされる
スーパークラス→サブクラスの変換は明示 的なキャストが必要
自動的
I t emType明示的
- i d - name - pr i ce
Obj ect
12.2 継承 VS 委譲
12.2.1 継承による設計
12.2.2 委譲による設計
12.2.3 継承 VS 委譲
12.2.1 継承による設計
一つの疑問
継承を利用して解決したほうがよいのでは ないか?
金種類リスト + 追加( ) + 削除( ) + 検索( ) + 表示( )
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( ) 汎用リスト
+ 追加( ) + 削除( )
12.2.2 委譲による設計
現状の設計
商品種類リスト、金種類リストが汎用 List クラスに要素の管理を任せている設計
金種類リスト + 追加( ) + 削除( ) + 検索( )
+ 表示( ) 汎用リスト + 追加( ) + 削除( ) 商品種類リスト
+ 追加( ) + 削除( ) + 検索( ) + 表示( )
継承 VS 委譲
それぞれの設計の利点・欠点を考える
継承を使った設計 委譲を使った設計
金種類リスト + 追加( ) + 削除( ) + 検索( )
+ 表示( ) 汎用リスト + 追加( ) + 削除( ) 商品種類リスト
+ 追加( ) + 削除( ) + 検索( ) + 表示( )
金種類リスト + 追加( ) + 削除( ) + 検索( ) + 表示( )
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( ) 汎用リスト
+ 追加( ) + 削除( )
プログラムイメージ
public class ItemTypeList extends ObjectList{
public void add(ItemType itemType){
super.add(itemType);
} }
public class ItemTypeList {
private ObjectList objectList;
public void add(ItemType itemType){
objectList.add(itemType);
} }
委譲による設計
継承による設計
① 継承の利点が発揮される時
クラスに共通の意味がある場合に、利 用するプログラムが共通の意味に注目 したプログラムを書くことができる
共通の意味に注目できる 共通の意味に注目できる
商品種類配列リスト 商品種類連結リスト Mai n
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( )
金種類
- 価値 商品種類
- 商品番号
- 商品名
- 価格
リスト要素 汎用リスト
+ 追加( ) + 削除( )
② 継承の利点は生かされるか
利用するプログラム
???
金種類リストか、商品種類リストを意識せず、汎用的な List に対してプログラムを書く場合が果たしてあるか?
金種類リスト + 追加( ) + 削除( ) + 検索( )
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) 汎用リスト
+ 追加( ) + 削除( )
③ プログラムの意味に注目す る
金種類リストを利用するプログラムは金種類リストを追加した い
商品種類リストを利用するプログラムは商品種類リストを追加 したい
金種類リストを
利用するプログラム 金種類を追加する
商品種類リストを
利用するプログラム 商品種類を追加する
金種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( )
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( )
金種類リスト + 追加( ) + 削除( ) + 検索( ) + 表示( )
商品種類リスト + 追加( )
+ 削除( ) + 検索( ) + 表示( ) 汎用リスト
+ 追加( ) + 削除( )
プログラムの意味に注目する (2)
各クラスのメソッドの意味が異なって いる
目的 - 手段の関係ではない
Object をリストに追加する
商品種類を商品種類リスト に追加する
金種類を金種類リスト
に追加する
良いように見えるけど
こうして考えると、商品種類リストと金 種類リストは意味がまったく異なること が分かる
絶対に間違いということはないが、継承を使 う利点はなくなるのでは?
逆に様々な欠点が浮かび上がる
多重継承はできないことに注意する
ex)
リストの実装を変更したい場合どうするか 金種類リストを連結リストでの実装に
商品種類リストを配列での実装に
12.3 JavaAPI を利用する
12.3.1 JavaAPI
12.3.2 リスト周りの API
12.3.3 JavaAPI を利用したプログラム
12.3.4 JavaAPI ドキュメント
12.3.1 JavaAPI
List のようなクラスはとてもよく使う
プログラミングのたびに自作するのは面倒 だ
汎用的な List は再利用できる
Java では汎用的で便利なクラス群が用意されている
Java クラス・ライブラリ
API とは?
ライブラリ
(クラス群)
あなたが作る アプリケーション・
プログラム
Application Programming Interface
アプリケーションプログラムを書くための インターフェイス
API を通じて
ライブラリを利用する
12.3.2 リスト周りの API
Java で用意されているリスト
List(Interface)
ArrayList
配列で実装されたリスト
LinkedList
連結リストで実装されたリスト
Li st
ArrayLi st Li nkedLi st
List
API( 抜粋 )
List インターフェイスの主なメソッド
void add(Object object)
void remove(Object object)
int size()
Object get(int index)
つまり、 ArrayList,LinkedList クラスでこれらのメソッドが使える
使い方は今回作った List と同じ
LinkedList
LinkedList クラスの特別なメソッド
void addFirst(Object object)
void addLast(Object object)
void removeLast(Object object)
void removeFirst(Object object)
このメソッドを使えば、簡単にキュー、スタックを作ることが
できます
12.3.3
JavaAPI を利用したプログラ
ム
import java.util.*;//java.util
クラスライブラリの利用を宣言する // 商品種類リストクラスpublic class ItemTypeList {
private ArrayList itemTypeList;
// コンストラクタ
public ItemTypeList() {
itemTypeList = new ArrayList();
}
// リストに商品種類を追加する
public void add(ItemType newItemType){
itemTypeList.add(newItemType);
今まで作ってきた List クラス
は
JavaAPI そっくりに作って
きたため、
変更点は 3
箇所のみ例題 12-3
(ItemTypeList.java)
12.3.4 JavaAPI ドキュメント
Java が提供する多くのクラスとその API( メソッドの書式など ) をまとめた マニュアル
これを使えば知らない機能や知らないクラ スなども調べて使うことができます