データ構造とアルゴリズムの結 第6回 合
~手続き指向からオブジェクト指向へ [ ] Ⅱ
~
学習目標
データ構造とアルゴリズムを結合させた クラスを使ったプログラムが書ける
データ構造とアルゴリズムが結合することの 利点を説明できる
クラスのデータをカプセル化することができ る データをカプセル化することの利点を説明できる
クラス図が読める6.1 アルゴリズムと データ構造の結合
6.1.1 仕様変更に伴う Main プログラム の変更
6.1.2 問題の本質
6.1.3 データ構造とアルゴリズムの結合
6.1.4 データ構造とアルゴリズムを結合
したプログラムを書く
6.1.1 仕様変更
① 配列リストによる商品種類プログラ ム
② 実装方法変更
③ またまた実装変更!?
① 配列リスト②連結リスト
① 第 4 回で実装した配列版 ItemTypeList クラス
今回はItemTypeArrayList
クラスとします ② 第 5 回で実装した連結リスト版 ItemTypeList クラス
今回はItemTypeLinkedList
クラスとします③ 戻したら動かなくなった
// 例題 6-3 :また仕様変更
public class Example6_3 {
//
取り扱う商品種類を追加するプログラムpublic static void main(String[] args) {
//
商品種類配列リストを生成する
ItemTypeArrayList itemTypeList = new ItemTypeArrayList();
//
商品種類を保存するための配列を定義するItemType[] itemTypeArray = new ItemType[100];
//
商品種類を追加する
for(int i=0;i<100;i++){
itemTypeList.add(itemTypeArray,new ItemType(i,"
コーラ ",120));}
// 商品種類リストを表示する
itemTypeList.display(itemTypeArray);
} }
例題
6-3
(Example6_3.java)
どこがまずいのか 考えてみよう
実は ItemTypeList が原因
/** * 商品種類を追加する
*/ public void add(ItemType[] targetArray,ItemType addItemType){
//
商品種類が入っていない箱を探す for(int i=0;i<10;i++){if(targetArray[i] == null){//
入っていない targetArray[i] = addItemType;//
書き込む break;} } }
例題
4-5
(Example4_5.java)
6.1.2 問題の本質
ケアレスミスを防ぐことはできない
人間が書くものだから
ケアレスミスをした時に原因を発見できるプ ログラムを書くほうが重要
他人に分かるように書く クラスは意味のカタマリに
プログラムは意味を明確に
問題の本質を探ってみよう
① クラスの役割分担から
② 意味が明確なプログラムという面から① クラスの役割分担
Example にバグがあると思った
ら、 ItemTypeList に原因があった
役割分担がうまくいってないExample
① クラスの役割分担
配列版
連結リスト版
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1
配列を持ってるExample
102番地 コーラ
22(id)
null ソーダ
23(id)
連結リストを 持ってる
ItemTypeList
ItemTypeList
配列操作アルゴリズムを 持ってる
連結リスト操作 アルゴリズムを 持ってる
add()
insert()
add()
insert()
② 意味が明確なプログラム
現状のプログラムは、データ構造(
配列)
を気にしす ぎる より意味が明確なプログラムのほうが、意図した動作を期 待しやすい
// メインクラス
public class Example6_3 {
//取り扱う商品種類を追加するプログラム
public static void main(String[] args) { //商品種類配列リストを生成する
ItemTypeArrayList itemTypeList = new ItemTypeArrayList();
//商品種類を保存するための配列を定義する
ItemType[] itemTypeArray = new ItemType[100];
//商品種類を追加する
for(int i=0;i<100;i++){
itemTypeList.add(itemTypeArray,new ItemType(i,"
コーラ ",120));}
// 商品種類リストを表示する
itemTypeList.display(itemTypeArray);
「商品種類リスト」に
「商品種類」を追加する
「配列」に
「商品種類」を追加する 現在のプログラム
本来の意味
(
目的)
ItemTypeLinkedList
② 意味が明確なプログラム
Example
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1
102番地 コーラ
22(id)
null ソーダ
23(id)
ItemTypeArrayList
配列操作アルゴリズム
連結リスト操作 アルゴリズム
add()
insert() add()
insert()
やりたいんなにを だっけ?
6.1.3 データ構造と アルゴリズムの結合
2つ合わせて初めて意味がある
配列を使うには
連結リストを使うには
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1
配列用アルゴリズム
add()
delete() search() display()
102番地 コーラ
22(id)
null ソーダ
23(id)
連結リスト用アルゴリズム
add()
delete()
search()
display()
6.1.3 アルゴリズム とデータ構造の結合
データ構造とアルゴリズムを結合して
「意味のカタマリ」を作る
2つ合わせて初めて「リスト」という意味 があるItemTypeArrayList [5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1
配列操作アルゴリズム
add()
insert()
Java でのプログラム(配列)
// 商品種類リスト配列実装クラス
public class ItemTypeArrayList {
public ItemType[] itemTypeArray;//
商品種類を保存する配列 // 商品種類を追加するメソッドpublic void add(ItemType addItemType){
//
商品種類が入っていない箱を探す for(int i=0;i<10;i++){if(itemTypeArray[i] == null){//
入っていない itemTypeArray[i] = addItemType;//書き込む break;} } } }
データ構造
アルゴリズム それを操作すると
例題
6-4
(Example6_4.java)
Java でのプログラム(連結リ スト)
// 商品種類リスト連結リスト実装クラス
public class ItemTypeLinkedList {
public LinkObject first;//
連結リスト始点 public LinkObject last;//連結リスト終点 // 商品種類を追加するメソッド
public void add(ItemType addItemType){
LinkObject addLink = new LinkObject();
addLink.data = addItemType;
if(first == null){//
連結リストが空のとき first = addLink;last = addLink;
}else{//
連結リストが空でないときlast.next = addLink;
last = addLink;
} } }
データ構造
アルゴリズム それを操作すると
例題
6-5
(Example6_5.java)
データ構造と
アルゴリズムを結合する利点
議論してみましょう
① うまい役割分担
役割分担を考え、各オブジェクトが責 任を持ち、うまくコミュニケーション できるようにするのがオブジェクト指 向設計の基本です
ItemTypeArrayList Example
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1
配列操作アルゴリズム
add()
insert()
商品種類の管理役命令役
② 意味が明確なプログラム
// 商品種類リストオブジェクトをインスタンス化する
ItemTypeArrayList itemTypeArrayList = new ItemTypeArrayList();
//
商品種類を追加するitemTypeArrayList.add(new ItemType(1001,"
コーラ "));// 商品種類リストを表示する
itemTypeArrayList.display();
より意味が明確な プログラムに
例題
6-4
(Example6_4.java) Main()
//
商品種類配列リストを生成するItemTypeArrayList itemTypeList = new ItemTypeArrayList();
//
商品種類を保存するための配列を定義するItemType[] itemTypeArray = new ItemType[100];
//
商品種類を追加するitemTypeList.add(itemTypeArray,new ItemType(1001,"
コーラ ",120));// 商品種類リストを表示する
itemTypeList.display(itemTypeArray);
ItemTypeArrayList
② 意味が明確なプログラム
ItemTypeLinkedList Example
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1
コーラ 22(id)
ソーダ 23(id)
配列操作アルゴリズム
連結リスト操作 アルゴリズム
add()
insert() add()
insert() 1001
追加
1001
追加② 意味が明確なプログラム
「商品種類」を「リスト」に追加する という意味の明確なプログラムが書け る
ItemTypeArrayList
Example 1001
追加
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1
配列操作アルゴリズム
add()
insert()
バグの発見が容易
人間は意味のカタマリに注目して、物事を考える
責任分担をして、「意味のカタマリ」を作り、意味 の明確なプログラムを書くことが重要、可読性も上 がるItemTypeArrayList Example
1001
追加??
オマエが悪い!
6.2 カプセル化
6.2.1 不正な操作
6.2.2 不正な操作を防ぐ
6.2.3 Java におけるカプセル化
①Java
で使えるアクセス修飾子 6.2.4 商品種類クラスのカプセル化
6.2.1 不正な操作
以下の例は、誤った ItemTypeArrayList の使い方です
// 商品種類リストオブジェクトをインスタンス化する
ItemTypeArrayList itemTypeArrayList = new ItemTypeArrayList();
//
商品種類を追加するitemTypeArrayList.add(new ItemType(1001,"
コーラ "));itemTypeArrayList.add(new ItemType(1002,"
ソーダ "));itemTypeArrayList.itemTypeArray[0] = null;
これでもプログラムは動いてしまいます!
不正な ItemTypeArrayList の使い方
ItemTypeArrayList Example
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1 add()
insert()
ItemTypeArrayList
Example 1001
追加
[5]
[4]
[3]
[2]
[1]
[0] -1 -1 -1 -1 -1 -1 add()
insert()
正規の操作不正な操作
1055
不正はバグの原因
ItemTypeArrayList は、直接配列をいじ られるようには作られていません
間にnull
等が入ると、おかしな動作をして しまいます意味が明確な add メソッドを利用して欲しい
6.2.2 不正な操作を防ぐ
add()
insert() [0] -1 -1 -1 -1 -1 -1 [1] [2] [3] [4] [5]
ItemTypeArrayList
データの「カプセル化」をして、オブ ジェクトの外から参照できないように します
参照できるのはメソッドだけ6.2.3 Java におけるカプセル 化
「 public 」だったアクセス修飾子を
「 private
// 商品種類リスト配列実装クラス」に変えます
public class ItemTypeArrayList {
private ItemType[] itemTypeArray;//
商品種類を保存する配列 // 商品種類を追加するメソッドpublic void add(ItemType addItemType){
//
商品種類が入っていない箱を探す for(int i=0;i<10;i++){if(itemTypeArray[i] == null){//
入っていない itemTypeArray[i] = addItemType;//書き込む break;}
}
}
}
不正できなくなる
// 商品種類リストオブジェクトをインスタンス化する
ItemTypeArrayList itemTypeArrayList = new ItemTypeArrayList();
//
商品種類を追加するitemTypeArrayList.add(new ItemType(1001,"
コーラ "));itemTypeArrayList.add(new ItemType(1002,"
ソーダ "));itemTypeArrayList.itemTypeArray[0] = null;
アクセス修飾子「
private
」がついていれば、コンパイルエラーとなります
① Java で使えるアクセス修飾 子
public
すべてのクラスから参照可能 private
そのクラス内でのみ参照可能 protected
そのクラスとそのサブクラスでのみ参照可能
何もつけない
パッケージ内でのみ参照可能アクセス修飾子を
理解できたか、簡単なテスト
/*** アクセス修飾子を解説するためのクラス
*/
public class Access{
public int dataA;
private int dataB;
private int getDataA(){
return dataA;
}
public int getDataB(){
return dataB;
}
}
答え
外部クラス
Access
クラスgetDataA
メソッドgetDataB
メソッドdataA
dataB
G
6.2.4
商品種類クラスのカプセル化
現状の ItemType クラス
// 商品種類のクラス
public class ItemType{
int id; //
商品番号
String name; //
商品名 // コンストラクタpublic ItemType(int initId, String initName){
id = initId;
name = initName;
}
}
保守性を高くした ItemType クラス
// 商品種類のクラス
public class ItemType{
private int id; //
商品番号 private String name; // 商品名 // コンストラクタ
public ItemType(int initId, String initName){
id = initId;
name = initName;
}
//
商品番号を得るメソッドpublic int getId(){
return id;
}
//
名前を得るメソッド
public String getName(){
return name;
} }
商品番号と商品名への 直な参照を禁止します。
変わりに、
public
でそれらを得ることができる メソッドを用意します。
これで、商品番号と商品名はコンストラクタで
例題
6-6
(Example6_6.java)
外部から設定変更を許すとき
// 商品種類のクラス
public class ItemType{
private int id; //
商品番号 private String name; // 商品名// コンストラクタ省略 // 商品番号を得るメソッド
public int getId(){
return id;
}
//
名前を得るメソッドpublic String getName(){
return name;
}
//
名前を設定するメソッドpublic void setName(String newName){
name = newName;
}
変更を許す属性にのみ
public
な変更メソッドを 用意します何故設定と取得を分けるの?
// 商品種類のクラス
public class ItemType{
public String name; //
商品名}
// 商品種類
public class ItemType{
private String name; //
商品名//
名前を得るpublic String getName(){
return name;
}
//
名前を設定するpublic void setName(String newName){
name = newName;
} }
VS
itemType.name = "
コーラ ";System.out(itemType.name)
itemType.setName("
コーラ ")System.out(itemType.getName())
利用する時を 考えよう
利用するクラスから見れば
System.out.println(itemTypeArray[i] .name+"
は販売中です ");System.out.println(itemTypeArray[i].getName()+"
は販売中です "); ItemTypeList の変更
意味が明らか 取得?設定?
コンパイルエラー
設定と取得を分ける理由
クラスを利用する側から見れば
取得なのか設定なのか明確なプログラムが 書ける クラスから見れば、
取得はできるけど設定はできない変数
設定されたら困る変数
取得した時だけログをとりたい場合
設定した時だけログをとりたい場合6.3 クラスの構造を図解する
6.3.1 クラス図とは
6.3.2 記法
① クラスを表現する
② クラス間の関係を表現する 6.3.3 今回までのクラス図
6.3.1 クラス図とは
Example,ItemType,ItemTypeList など、
クラスの構成が複雑化してきました
見やすいように図解する方法
クラス図
クラス図
クラス図はクラス構造を分かりやすく するためのものです
Li nkObj ect +next
I t emTypeLi nkedLi st + add( )
+ del et e( ) + sear ch( ) + di spl ay( ) Mai n
+ mai n( )
1 1
1 1
I t emType - i d
- name + get I d( ) + get Name( ) 0. . n
1
0. . n 1
I t emTypeAr r ayLi st + add( )
+ del et e( ) + sear ch( ) + di spl ay( ) 1
1
1
1 0. . n
1
0. . n 1
記法①クラス
クラス名 変数
メソッド 可視性
public+
private -
I t emType - i d
- name
+ get I d( )
+ get Name()
記法②関係
「関係」は、 Java で参照を持っている ことを意味し、線で結びます
List
クラスはItemType
を変数(配列)で 参照しているので関係がありますI t emTypeAr rayLi st + add( )
+ del et e( ) + sear ch( ) + di spl ay( )
I t emType - i d
- name + get I d( ) + get Name( )
1 0. . n
1 0. . n
I t emTypeAr rayLi st + add( )
+ del ete( ) + sear ch( ) + di spl ay( )
I t emType - i d
- name + get I d( ) + get Name( )
1 0. . n
1 0. . n
1003
多重度
単なる関係だけではインスタンスを何 個参照しているのか分からないので、
多重度をつかいます
クラス
オブジェクト
1002
ソーダ コーラ
1001
itemType ArrayList
1対 n の関係
今回までのクラス図
Li nkObj ect +next
I t emTypeLi nkedLi st + add( )
+ del et e( ) + sear ch( ) + di spl ay( ) Mai n
+ mai n( )
1 1
1 1
I t emType - i d
- name + get I d( ) + get Name( ) 0. . n
1
0. . n 1
I t emTypeAr r ayLi st + add( )
+ del et e( ) + sear ch( ) + di spl ay( ) 1
1
1
1 0. . n
1
0. . n 1