第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) { 例題6-3 (Example6_3.java) //商品種類配列リストを生成する 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); } } どこがまずいのか 考えてみよう 実はItemTypeListが原因 例題4-5 (Example4_5.java) /** * 商品種類を追加する */ public void add(ItemType[] targetArray,ItemType addItemType){ //商品種類が入っていない箱を探す for(int i=0;i<10;i++){ if(targetArray[i] == null){//入っていない targetArray[i] = addItemType;//書き込む break; } } } 6.1.2 問題の本質 ケアレスミスを防ぐことはできない 人間が書くものだから ケアレスミスをした時に原因を発見できるプログ ラムを書くほうが重要 他人に分かるように書く クラスは意味のカタマリに プログラムは意味を明確に 問題の本質を探ってみよう ①クラスの役割分担から ②意味が明確なプログラムという面から ①クラスの役割分担 Exampleにバグがあると思ったら、 ItemTypeListに原因があった 役割分担がうまくいってない ①クラスの役割分担 配列版 配列を持ってる -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] Example 連結リスト版 ItemTypeList 連結リストを 持ってる 22(id) 23(id) コーラ ソーダ 102番地 Example null 配列操作 アルゴリズムを 持ってる add() insert() 連結リスト操作 アルゴリズムを 持ってる add() insert() ItemTypeList ②意味が明確なプログラム 現状のプログラムは、データ構造(配列)を気にしすぎる より意味が明確なプログラムのほうが、意図した動作を期待しや すい //メインクラス 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); } } 「商品種類リスト」に 「商品種類」を追加する ②意味が明確なプログラム 配列操作 アルゴリズム -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] ItemTypeArrayList add() insert() Example 22(id) 23(id) コーラ ソーダ 102番地 null なにを やりたいん ItemTypeLinkedList だっけ? 連結リスト操作 アルゴリズム add() insert() 6.1.3 データ構造と アルゴリズムの結合 2つ合わせて初めて意味がある 配列を使うには -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] 連結リストを使うには 22(id) 23(id) コーラ ソーダ 102番地 null 配列用アルゴリズム add() delete() search() display() 連結リスト用アルゴリズム add() delete() search() display() 6.1.3 アルゴリズム とデータ構造の結合 データ構造とアルゴリズムを結合して 「意味のカタマリ」を作る 2つ合わせて初めて「リスト」という意味がある -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] 配列操作 アルゴリズム add() insert() ItemTypeArrayList Javaでのプログラム(配列) //商品種類リスト配列実装クラス public class ItemTypeArrayList { 例題6-4 (Example6_4.java) public ItemType[] itemTypeArray;//商品種類を保存する配列 //商品種類を追加するメソッド public void add(ItemType addItemType){ //商品種類が入っていない箱を探す for(int i=0;i<10;i++){ if(itemTypeArray[i] == null){//入っていない itemTypeArray[i] = addItemType;//書き込む break; } } } } データ構造 と それを操作する アルゴリズム 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) データ構造 と それを操作する アルゴリズム データ構造と アルゴリズムを結合する利点 議論してみましょう ①うまい役割分担 役割分担を考え、各オブジェクトが責任を 持ち、うまくコミュニケーションできるように するのがオブジェクト指向設計の基本です 商品種類の管理役 命令役 -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] 配列操作 アルゴリズム Example ItemTypeArrayList add() insert() ②意味が明確なプログラム //商品種類配列リストを生成する ItemTypeArrayList itemTypeList = new ItemTypeArrayList(); //商品種類を保存するための配列を定義する ItemType[] itemTypeArray = new ItemType[100]; //商品種類を追加する itemTypeList.add(itemTypeArray,new ItemType(1001,"コーラ",120)); //商品種類リストを表示する itemTypeList.display(itemTypeArray); 例題6-4 (Example6_4.java) //商品種類リストオブジェクトをインスタンス化する Main() ItemTypeArrayList itemTypeArrayList = new ItemTypeArrayList(); //商品種類を追加する itemTypeArrayList.add(new ItemType(1001,"コーラ")); //商品種類リストを表示する itemTypeArrayList.display(); より意味が明確な プログラムに ②意味が明確なプログラム -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] Example 1001 追加 1001 追加 配列操作 アルゴリズム ItemTypeArrayList add() insert() 連結リスト操作 ItemTypeLinkedList アルゴリズム 22(id) 23(id) コーラ ソーダ 102番地 null add() insert() ②意味が明確なプログラム 「商品種類」を「リスト」に追加するという意 味の明確なプログラムが書ける -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] Example 配列操作 アルゴリズム 1001 追加 ItemTypeArrayList add() insert() バグの発見が容易 人間は意味のカタマリに注目して、物事を考える 責任分担をして、「意味のカタマリ」を作り、意味の明確な プログラムを書くことが重要、可読性も上がる 1001 Example 追加 ItemTypeArrayList ?? オマエが悪い! 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の使い方 -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] 正規の操作 Example 不正な操作 Example 1001 追加 add() insert() ItemTypeArrayList 1055 -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] add() insert() ItemTypeArrayList 不正はバグの原因 ItemTypeArrayListは、直接配列をいじら れるようには作られていません 間にnull等が入ると、おかしな動作をしてしま います 意味が明確なaddメソッドを利用して欲しい 6.2.2 不正な操作を防ぐ データの「カプセル化」をして、オブジェクト の外から参照できないようにします 参照できるのはメソッドだけ ItemTypeArrayList add() insert() -1 -1 -1 -1 -1 -1 [0] [1] [2] [3] [4] [5] 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; } } 答え 外部クラス getDataA メソッド dataA dataB getDataB メソッド G Access クラス 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; // 商品名 例題6-6 (Example6_6.java) 商品番号と商品名への 直な参照を禁止します。 //コンストラクタ public ItemType(int initId, String initName){ id = initId; name = initName; } //商品番号を得るメソッド public int getId(){ return id; } //名前を得るメソッド public String getName(){ return name; } } 変わりに、publicで それらを得ることができる メソッドを用意します。 これで、商品番号と商品名はコンストラクタで 一旦設定されたら、外部から変更できなくなりました。 外部から設定変更を許すとき //商品種類のクラス 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{ private String name; // 商品名 //商品種類のクラス public class ItemType{ public String name; // 商品名 } //名前を得る public String getName(){ return name; } VS //名前を設定する public void setName(String newName){ name = newName; } } 利用する時を 考えよう itemType.name = "コーラ"; System.out(itemType.name) itemType.setName("コーラ") System.out(itemType.getName()) 利用するクラスから見れば ItemTypeListの変更 コンパイル エラー 取得?設定? System.out.println(itemTypeArray[i].name+"は販売中です"); System.out.println(itemTypeArray[i].getName()+"は販売中です"); 意味が明らか 設定と取得を分ける理由 クラスを利用する側から見れば 取得なのか設定なのか明確なプログラムが書 ける クラスから見れば、 取得はできるけど設定はできない変数 設定されたら困る変数 取得した時だけログをとりたい場合 設定した時だけログをとりたい場合 6.3 クラスの構造を図解する 6.3.1 クラス図とは 6.3.2 記法 ①クラスを表現する ②クラス間の関係を表現する 6.3.3 今回までのクラス図 6.3.1 クラス図とは Example,ItemType,ItemTypeListなど、ク ラスの構成が複雑化してきました 見やすいように図解する方法 クラス図 クラス図 クラス図はクラス構造を分かりやすくする ためのものです ItemTypeArrayList Main + main() 1 add() delete() search() display() + 1 + + + 1 0..n ItemTypeLinkedList 1 1 + + + + add() delete() search() display() +next LinkObject 1 ItemType - id - name 0..n + getId() + getName() 記法①クラス ItemType 可視性 public+ private - - id - name + getId() + getName() クラス名 変数 メソッド 記法②関係 「関係」は、Javaで参照を持っていることを 意味し、線で結びます ListクラスはItemTypeを変数(配列)で参照し ているので関係があります ItemType ItemTypeArrayList + + + + add() delete() search() display() - id - name 1 + getId() 0..n + getName() 多重度 単なる関係だけではインスタンスを何個参 照しているのか分からないので、多重度を つかいます ItemType ItemTypeArrayList クラス + + + + オブジェクト add() delete() search() display() - id - name 1 + getId() 0..n + getName() 1対nの関係 itemType ArrayList 1001 コーラ1002 ソーダ 1003 お茶 今回までのクラス図 ItemTypeArrayList Main + main() 1 + 1 + + + add() delete() search() display() 1 0..n ItemTypeLinkedList 1 1 + + + + add() delete() search() display() +next LinkObject 1 ItemType - id - name 0..n + getId() + getName()
© Copyright 2024 ExpyDoc