JavaとUMLで学ぶオブジェクト指向の考え方 第三章 高度なオブジェクト指向の概念 2003年6月16日 荒木研究室 学部4年 藤井 亮太 この章の目的 より高度なオブジェクト指向の概念 オブジェクトの作成と初期化 エラー処理 オブジェクトのコピーと比較 コンストラクタ オブジェクトの構築に使用する特別なメソッド クラスと同じ名前 戻り値を持たない 例 public Cabbie(){ /* オブジェクトを構築するためのコード */ } コンストラクタが呼び出されるとき(1) 新しいオブジェクトを作成すると、最初にコンストラクタが 呼び出される。 Cabbie MyCabbie = new Cabbie newキーワードでメモリ内にCabbieオブジェクトをインスタンス化し、 コンストラクタが呼び出される コンストラクタ内のコードが実行された後、MyCabbie変数に 生成されたオブジェクトへのポインタが渡される。 コンストラクタが呼び出されるとき(2) 新しいオブジェクトを作成するときの概念 クラス Class class = new Object() オブジェクト コンストラクタ オブジェクト オブジェクト コンストラクタの内部と デフォルトコンストラクタ コンストラクタ内のコードで属性の初期化を記述する クラスにコンストラクタが明示されていない場合は デフォルトコンストラクタが提供される 上位(親)クラスのコンストラクタを呼び出すのみ 初期化する属性が無くとも、コンストラクタを 記述する習慣は付けておいたほうが良い。 複数のコンストラクタの使用(1) メソッドのオーバーロードによって、 オブジェクトの構築法を変えることができる。 オーバーロード シグニチャが異なる限り、同じ名前のメソッドを 何個でも作ることができる。 public String getRecord(int key) シグニチャ = getRecord メソッド名 + (int key) パラメータリスト 複数のコンストラクタの使用(2) DataBaseReaderの例 public class DataBaseReader{ string dbName; int startPosition; //名前だけを初期化 public DataBaseReader (string name){ dbName = name; }; //名前と位置を初期化 public DataBaseReader (string name,int pos){ dbName = name; startPosition = pos; }; ......//クラスの残り部分 } スーパークラスの構築方法(1) newでオブジェクトが割り当てられたときの処理の順番 1.コンストラクタ内で、最初にそのクラスのスーパークラスの コンストラクタが呼び出される。 2.オブジェクトの各クラス属性が初期化される。 3.コンストラクタ内の残りのコードが実行される。 スーパークラスの構築方法(2) オブジェクトの構築 DataBaseReaderの コンストラクタを呼び出す ユーザー クラス DataBase Reader クラス スーパー クラス 最初にスーパークラスの コンストラクタを呼び出す エラー処理 エラーが起きた際の対処方法 不具合を無視する 不具合を調査し、不具合を検出したらプログラムを終了する 潜在的な問題を調査し、誤りを見つけて修正する 例外をスローする 不具合を無視する エラーを無視したアプリケーションは、最終的に 異常終了するか、不安定な状態のまま 処理を続けることになる。 不具合は無視するべきではない 不具合を調べて アプリケーションを終了する 不具合が検出されるたびに、障害のメッセージを表示 ファイルクローズなどの処理をし、安定した状態に 移行できる 不具合を無視するよりは望ましい ただし、最善の方法ではない 不具合を調べて回復を試みる 誤りを見つけて、それを回避するようコードに記述を修正 最初にどこで不具合が発生するかわからない 不具合の検出に時間がかかる、などの問題がある 例 if (a == 0) a=1; c = b/a; c = b/a; の時、ゼロ除算が回避できる 例外をスローする(1) 例外(exception) システム内で発生するエラー 不具合を検出して処理するための手段を提供 例外をスローする(2) 記述例 try { // 問題を起こすかもしれないコード count = 0 ; count = 5/count ; } catch( Exception e ) //例外を処理するコード System.out.println(e.getMessage()) ; count = 1; } System.out.println(“The exception is handled”) ; tryブロックで例外がスローされるとcatchブロックがそれを受け取る。 例外をスローする(3) 例外がスローされた場合の動作 1.現在のtryブロックの実行が終了 2.発生した例外に対応するcatchブロックがあるか判定 3.無ければ1つ上のレベルのtryブロックに渡され、繰り返す コード内でキャッチ無ければ、システムが例外をキャッチ(結果は不定) 4.例外に対応するcatch節が見つかれば、そのコード内の記述を実行 5.tryブロックの直後のステートメントから実行が再開 例外をスローする(4) 図例 システム システムが 例外をスローする システム アプリ ケーション アプリケーションが例外を キャッチして処理する これでOK スコープの概念 属性の種類 ローカル属性 オブジェクト属性 クラス属性 スコープ 属性は特定のスコープの中に存在 クラス自体が独自のスコープを持ち、 クラスのインスタンスや、クラス内のメソッドも それぞれのスコープを持つ スコープと属性 右図での3つの変数countは すべて異なるもの public class Number{ int count; public method1 (){ int count; }; class宣言直後のcountがオブジェクト属性 method1のcountとmethod2のcountが ローカル属性にあたる public method2 (){ int count; }; } ローカル属性 特定のメソッドに対してローカルな属性 public class Number{ method1で宣言されたcountは method1のコード内でのみアクセス可能 public method1 (){ int count; }; 他のメソッドからはアクセスできない そのメソッドが呼び出された時のみ countのコピーが作成される public method2 (){ int count; }; } オブジェクト属性(1) クラス内のすべてのメソッドがこの属性にアクセス可能 method1とmethod2のcount代入は メモリの同じコピーに対して行われる public class Number{ int count; 異なるオブジェクト間では オブジェクト属性は共有されない public method1 (){ count = 1; }; public method2 (){ count = 2; }; } オブジェクト属性(2) オブジェクト属性の図例 オブジェクト Number1 オブジェクト Number2 オブジェクト Number3 メモリ割り当て Count属性 メモリ割り当て Count属性 メモリ割り当て Count属性 Number1のcountを変更しても、 Number2と Number3のcountは影響を受けない スコープの例 メソッド内では、同じ名前の属性があれば 通常ローカル属性を指す public class Number{ int count; public method1 (){ int count; → “count = 2” がローカル属性への操作 this.count = 1; count = 2; オブジェクト属性を指定する場合は “this”キーワードを用いる }; public method2 (){ int count; }; → “this.count = 1” がオブジェクト属性への操作 } クラス属性(1) 異なるオブジェクト間で共有できる 属性をstaticにすることで実現 public class Number{ static int count; 全ての同クラスオブジェクトに対して 共通のメモリに割り当てられる public method1 (){ } } クラス属性(2) クラス属性の図例 メモリ割り当て count属性 オブジェクト1 オブジェクト2 オブジェクト3 演算子のオーバーロード オペランド(識別子)の種類よって演算子の 意味が変わる X = 5 + 6; …数字の加算 String firstname = “Joe”, lastname = “Smith”; String Name = firstname + “ ” + lastname; …文字列の連結 Matrix A, B, C; C = A + B; …行列の加算 多重継承 1つのクラスが複数のクラスを継承 非常に強力な機能 反面、システムが複雑になる恐れがある Javaでは多重継承は提供されていない 代わりにインターフェイスの機能を提供 オブジェクトの操作(1) オブジェクトをコピーするときの問題点 オブジェクトを単純にコピーするだけでは、ポインタなどがある場合 “完全に(深い)”コピーした事にはならない 深いコピーを行うためには、ポインタの参照先を追って 再帰的に参照先のサブオブジェクトなどを 作成、コピーする必要がある オブジェクトの操作(2) オブジェクトの比較 オブジェクトを比較する場合も、コピーと同様に ポインタを考慮する必要がある 2つのオブジェクトの指すポインタの値が違っても 互いの参照先のオブジェクトの値も異なるとは限らない オブジェクトコピーと参照の例 浅いコピー 深いコピー クラスB クラスB を参照 クラスA クラスC を参照 クラスB を参照 クラスB を参照 クラスAの コピー クラスA クラスC を参照 クラスC クラスBの コピー クラスB 新しいコピー を参照 クラスAの コピー 新しいコピー を参照 クラスC を参照 クラスC クラスCの コピー まとめ オブジェクトの構築方法 スコープと属性 エラー処理 オブジェクトの構造
© Copyright 2024 ExpyDoc