chapter3

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の
コピー
まとめ
オブジェクトの構築方法
スコープと属性
エラー処理
オブジェクトの構造