オブジェクト指向基礎学習Ⅱ 平成20年7月1日 森田 彦
学習内容 オブジェクト指向の考え方 オブジェクト指向の実装(Java言語の場合)
Ⅰ.オブジェクト指向の考え方 1 オブジェクトとは何か? 2 オブジェクトの基本概念 3 オブジェクトの拡張 <内容> オブジェクト指向の考えのエッセンスを学習し、それをプログラム開発に応用した場合にどのようなメリットがあるかを理解する。 <内容> 1 オブジェクトとは何か? 2 オブジェクトの基本概念 3 オブジェクトの拡張
1.オブジェクトとは何か? オブジェクトの例 カプセル化(プロパティとメソッド) オブジェクト指向的考え
オブジェクトの例 人、車、黒板、机などのモノのこと。 オブジェクト指向の世界での定義→(自身の)状態に関する情報と、(自身に対する)操作を有するモノ。 例) 車 状態:型式、色、排気量、マニュアルかATか、等々。 操作:走る、停止する、等々。
(プロパティとメソッドの)カプセル化 オブジェクト→自身の状態を表すデータ+(自身に対する)操作を有するモノ データと操作の(オブジェクトへの)カプセル化 1セットにするという意味 車オブジェクト 色 排気量 走る 停止する データ プロパティ 操作 メソッド ・・・
補足 カプセル化の意味 情報の隠蔽の積極的意味 関連のあるメソッドとプロパティを組み合わせて1セットにする。 補足 カプセル化の意味 関連のあるメソッドとプロパティを組み合わせて1セットにする。 そのオブジェクトの(メソッドの)使い方以外は、情報を見せない→情報の隠蔽(データの保護という意味もある) 利用者は、オブジェクトの内部の詳細を知ることなく、オブジェクトに備わった機能(メソッド)を利用できる。 情報の隠蔽の積極的意味
オブジェクト指向的考え ある用途のためのオブジェクトがあれば・・・ そのオブジェクトのメソッドを操作することで、処理を実現 そのオブジェクトのメソッドを操作することで、処理を実現 例) ゼミでコンパを企画する。 オブジェクト→コンパ係 メソッド→企画 オブジェクト指向的記述→コンパ係.企画 (ドット記法) (意味:コンパ係に企画を依頼する。→コンパ係オブジェクトに企画せよというメッセージを送る。) プロパティとメソッドがカプセル化されたオブジェクトを用いれば、手続き型(指向)プログラミングよりも効率が上がる!? 操作(メソッド)の詳細を知る必要がない。
2.オブジェクトの基本概念 長方形オブジェクト クラスとインスタンス メソッドの継承 スーパクラスとサブクラス
長方形オブジェクト 長方形:高さと幅をプロパティとして持っている。 (ここでは)面積を求めるメソッド(操作)考える。 クラスの概念の登場 長方形A 高さ:7 幅:10 面積は? 高さ×幅 プロパティ(幅、高さ)の値によって、様々なオブジェクトがある。 幅と高さというプロパティは共通 一まとめに定義した方が便利 クラスの概念の登場
クラスとインスタンス クラス→共通の性質を持ったものの集まり 抽象化 実例 長方形クラス 長方形オブジェクト(インスタンス) 高さ: 幅: 面積は? 高さ×幅 抽象化 長方形クラス (プロパティとメソッドの定義を持つ) 長方形オブジェクト(インスタンス) 実例 長方形A 高さ:7 幅:10 長方形B 高さ:9 幅:5 ( 個々に異なるプロパティの値(のみ)を持つ ) メソッドはクラスから引き継ぐ
メソッドの継承 インスタンス(オブジェクト)がメッセージを受け取った時→自分が属するクラスのメソッドを起動する→メソッドの継承 長方形クラス 高さ: 幅: 面積は? 高さ×幅 長方形クラス 長方形オブジェクト(インスタンス) 長方形A メッセージ 面積は? 高さ:7 幅:10 面積は? 高さ×幅 70
スーパクラスとサブクラス(クラスの継承) 長方形と正方形の関係 正方形は長方形の一部→「高さ=幅」が成り立つ特別な長方形 長方形:広い範囲のインスタンスをカバーするクラス→スーパクラス 正方形:スーパクラスの一部のインスタンスのみをカバーするクラス→サブクラス
サブクラスを利用した正方形の定義 継承 長方形クラス スーパクラス 正方形クラス サブクラス 正方形オブジェクト(インスタンス) 長方形 高さ: 幅: 面積は? 高さ×幅 長方形クラス スーパクラス 継承 OMT(Object Modeling Technique)の記法 正方形 高さ=幅 正方形クラス サブクラス 正方形A 幅:10 正方形オブジェクト(インスタンス)
クラスの階層図(図形クラスの例) スーパクラスとサブクラスという概念は相対的なもの 図形 四角形 三角形 長方形 台形 正方形 サブクラス(下位のクラス)はスーパクラス(上位のクラス)の性質を全て引き継ぐ。 + 新たなプロパティあるいはメソッドを持つ。
3.オブジェクトの拡張性 ソフトウェアの生産性向上 単純なクラスに機能を付加→複雑なクラスを定義可能 既存のクラスに機能を付加→目的に応じたクラスを容易に定義できる ソフトウェアの生産性向上 オブジェクト指向プログラミングはソフトウェア危機の救世主!?
三角形クラスの定義 (多態性) 長方形クラスと三角形クラス、それぞれに異なる「面積は?」メソッドを定義 プログラムの拡張が容易に! 三角形クラスの定義 (多態性) 長方形.面積は? 図形 高さ: 幅: 長方形 面積は? 高さ×幅 三角形 高さ×幅/2 三角形.面積は? 同じ「面積は?」メッセージを受け取っても、長方形と三角形オブジェクト(インスタンス)では、振る舞いが違う。 ポリモフィズム(polymorphism:多態性) 長方形クラスと三角形クラス、それぞれに異なる「面積は?」メソッドを定義 プログラムの拡張が容易に!
デフォルトメソッドと上書き (定義の改良) デフォルトメソッドと上書き (定義の改良) 図形 高さ: 幅: 長方形 面積は? 高さ×幅 三角形 高さ×幅/2 デフォルトメソッド 多くの(しかし全てではない)インスタンスに適用できるメソッド メソッドの上書き サブクラスでメソッドを定義し直すこと <三角形クラスの異なる定義> プログラムの拡張が効率的に!
スーパ疑似変数と差分プログラム 「高さ×幅」の重複をなくす。 super:スーパ擬似変数 プログラムの拡張が効率的に! 図形 高さ: 幅: 長方形 面積は? 高さ×幅 三角形 super.面積は?/2 super:スーパ擬似変数 一つ上のクラスを表す。 拡張時にプログラムの重複を排除する上で有効 スーパクラスに何かを追加することでサブクラスのメソッドを定義する。 プログラムの拡張が効率的に! 継承を利用した差分プログラム 再利用性の向上!
理解度チェック 以下の設問に答えて下さい。 クラスとインスタンスの実例を挙げて下さい。 プログラムの再利用性を高める差分プログラムを可能にするのは、オブジェクト指向のどのような機能ですか?
クラスとインスタンス -プログラミングの場合 クラスとインスタンス -プログラミングの場合 クラス→ 型に対応 インスタンス(オブジェクト)→ 変数に対応 <通常の変数の場合> int a,b ; double x,y; <オブジェクト(インスタンス)の場合> JButton jButton1 = new JButton(); コンストラクタ JButtonクラス JButtonクラスのインスタンス
Ⅱ.オブジェクト指向の実装(Java言語の場合) <内容> フレームクラスの定義 人間クラスの定義 インスタンス(オブジェクト)の生成・利用 Java言語のメリット・デメリット
1.フレームクラスの定義(復習) <空っぽのフレームの場合> <Frame1クラスの定義> プロパティの定義 コンストラクタの定義 ・・・ } メソッドの定義 ・・・ }
フレームの生成 <Application1.javaファイル> フレームを生成する役割 frameの生成 Frame1クラスのインスタンス
インスタンスの生成(Java言語) Frame1 frame = new Frame1(); コンストラクタ クラス名 インスタンス名 クラスがあれば、インスタンス(オブジェクト)の生成は容易!
JBuilderによるJavaアプリケーションの構成 (補足) パッケージ(samplejava) <クラス> Frame1.java フレームクラスの定義 <クラス> Application1.java フレームを生成 役割分担の明確化! オブジェクト指向プログラミングの特徴
2.人間クラスの定義 サンプルプログラム 人間 動け:左右に動く 話せ:あいさつ 日本人 アメリカ人 イタリア人 話せ:こんにちは 話せ:Hello 話せ:Buon Giorno
① プログラム起動時 ③ [→]ボタンをクリックし、右へ移動 ④ [話す]ボタンをクリック ② 日本人を選択し[登場]ボタンをクリック ① プログラム起動時 ③ [→]ボタンをクリックし、右へ移動 ④ [話す]ボタンをクリック ② 日本人を選択し[登場]ボタンをクリック ⑤ [退場]ボタンをクリック
プログラムの構成 パッケージ humanmain クラスApplication1: フレームの生成 クラスFrame1: フレームの定義
人間クラスの定義 ボタンクラス(JButton)をスーパークラスに Moveメソッドの定義 Speakメソッドの定義 サブクラスを指す
人間クラスの定義(詳細) class Human extends JButton { 人間クラスの定義(詳細) class Human extends JButton { public void Move(int Dist) { Rectangle Rect; Rect=this.getBounds(); Rect.x=Rect.x+Dist; this.setBounds(Rect); } public void Speak() { this.setText("あいさつ"); 現在位置を取得 水平位置をずらす ずらした位置に表示(移動) thisはHumanクラスを指す。
日本人クラスの定義(継承) Humanクラス定義部の下に以下を追加 Humanクラスを継承 public void Speak() { class Japanese extends Human { public void Speak() { this.setText("こんにちは"); } メソッドの上書き Americanクラス、Italianクラスの定義も同様
3.インスタンスの生成・利用 Taro= new Japanese(); ① インスタンス(オブジェクト)名の宣言(Frame1クラス内) public class Frame1 extends JFrame { private Japanese Taro; private American John; private Italian Mario; ・・・ ② コンストラクタによるインスタンス生成 Taro= new Japanese(); アメリカ人およびイタリア人オブジェクト(インスタンス)の生成も同様
「登場」ボタン if(jRadioButtonJapan.isSelected()) { Taro=new Japanese(); void jButtonCreate_actionPerformed(ActionEvent e) { if(jRadioButtonJapan.isSelected()) { Taro=new Japanese(); contentPane.add(Taro); Taro.setBounds(new Rectangle(110,10,110,30)); Taro.setBackground(Color.white); Taro.setText(“Taro"); } else if(jRadioButtonAmerica.isSelected()) { ・・・ else if(jRadioButtonItaly.isSelected()) { 日本人インスタンス(Taro)を生成 x , y , w , h ボタンの大きさを設定 白色に設定 Taroと表示 アメリカ人インスタンス(John)の処理 イタリア人インスタンス(Mario)の処理
移動「→」ボタン 5歩右へ移動 if(jRadioButtonJapan.isSelected()) { Taro.Move(5); } void jButtonMoveRight_actionPerformed(ActionEvent e) { if(jRadioButtonJapan.isSelected()) { Taro.Move(5); } else if(jRadioButtonAmerica.isSelected()) { John.Move(5); else if(jRadioButtonItaly.isSelected()) { Mario.Move(5); 5歩右へ移動
「話す」ボタン 多態性の実現 if(jRadioButtonJapan.isSelected()) { Taro.Speak(); } void jButtonSpeak_actionPerformed(ActionEvent e) { if(jRadioButtonJapan.isSelected()) { Taro.Speak(); } else if(jRadioButtonAmerica.isSelected()) { John.Speak(); else if(jRadioButtonItaly.isSelected()) { Mario.Speak(); 多態性の実現
多態性のメリット(この例の場合) 日本人、アメリカ人そしてイタリア人それぞれにとって、“あいさつをする”という概念は共通。 ただ、個別的なあいさつの言葉が異なるだけ。 そこで、それら、個別の違いを気にせず、全て、Speak()というメソッドで(あいさつの表示を)実現できたら、プログラムの見通しが良く(読みやすく)、拡張も容易(ドイツ人、スペイン人クラスのインスタンスに対しても同様にプログラムできる)。 この様に、概念上同様の処理を、共通のメソッド名で表現し、処理内容の詳細がオブジェクト(インスタンス)に応じて異なっている様を多態性という。
「退場」ボタン サンプルプログラム if(jRadioButtonJapan.isSelected()) { void jButtonDelete_actionPerformed(ActionEvent e) { if(jRadioButtonJapan.isSelected()) { Taro.setVisible(false); } else if(jRadioButtonAmerica.isSelected()) { John.setVisible(false); else if(jRadioButtonItaly.isSelected()) { Mario.setVisible(false); サンプルプログラム
4.Java言語のメリット・デメリット (オブジェクト指向の観点から) オブジェクト指向プログラミングの記述が容易にできる。 オブジェクト指向の独特の記述が初心者には理解困難。 豊富なクラスライブラリが存在する。→色々な用途のアプリケーション開発が可能に。 クラスライブラリの全体像を把握する事が困難。
課題 解説で採りあげた、Java言語による人間クラスのプログラムを実際に作成して下さい。 作成して動作を確認した上で、森田までメールで「作成できました。」と送信して下さい。 宛先 hiko@sgu.ac.jp 〆切:本日中(7/1中)
補足) オブジェクト指向の難しさ ’90年代初頭の技術者は皆頭を悩ませた。 補足) オブジェクト指向の難しさ ’90年代初頭の技術者は皆頭を悩ませた。 オブジェクト指向の機能は便利。しかし、その活用方法のノウハウは当初は手探りだった・・・。 プログラマによってクラスの設計や継承の仕方(考え方)が異なるので、共有しにくい。 行き当たりばったりの継承が流行→スパゲッティ継承!? 現在は開発手法が整備されてきた。→クラスの設計や継承に関するルールが共有されるようになった。 きちんと教育を受ければ一定のレベルに到達するようになった。
Java言語におけるクラスの定義 class クラス名 { プロパティ(フィールド)の定義 コンストラクタの定義(初期化処理) コンストラクタの定義(初期化処理) メソッドの定義 }
クラスの継承 スーパークラス サブクラス public class Frame1 extends JFrame { プロパティの定義 プロパティの定義 コンストラクタの定義 メソッドの定義 } 全クラスから参照可能 コンポーネントはオブジェクト
復習)デフォルトメソッドと上書き (定義の改良) 復習)デフォルトメソッドと上書き (定義の改良) 図形 高さ: 幅: 長方形 面積は? 高さ×幅 三角形 高さ×幅/2 デフォルトメソッド 多くの(しかし全てではない)インスタンスに適用できるメソッド メソッドの上書き サブクラスでメソッドを定義し直すこと <三角形クラスの異なる定義> プログラムの拡張が効率的に!
人間クラスの継承図 スーパークラス サブクラス Taro John Mario インスタンス 人間 Move:左右に動く Speak:あいさつ サブクラス 日本人 アメリカ人 イタリア人 Speak:こんにちは Speak:Hello Speak:Buon Giorno Taro John Mario インスタンス
復習) 多態性(図形クラスの定義より) ポリモフィズム(polymorphism:多態性) 復習) 多態性(図形クラスの定義より) 長方形.面積は? 図形 高さ: 幅: 長方形 面積は? 高さ×幅 三角形 高さ×幅/2 三角形.面積は? 同じ「面積は?」メッセージを受け取っても、長方形と三角形オブジェクト(インスタンス)では、振る舞いが違う。 ポリモフィズム(polymorphism:多態性) 長方形クラスと三角形クラス、それぞれに異なる「面積は?」メソッドを定義 プログラムの拡張が容易に!
参考:言語の制約の度合い BASIC C 制約大 Java print “Hello!” 行が基本 main( ) { printf(“Hello!\n"); } C 関数が基本 public class Hello { public static void main(String args[ ]) { System.out.println(“Hello!”); } Java クラスが基本
一般に・・・ 一般に、オブジェクト指向言語は最も記述に手間がかかる。 ただ、プログラムの再利用性と見通しの良さは最も良い。 オブジェクト指向言語が威力を発揮するのは、大きなプログラムを共同で開発する時。
コンストラクタの記述 コンストラクタはインスタンス(オブジェクト)が生成される時に呼び出される特別なメソッド class Frame1 extends JFrame { public Frame1() { this.setSize(300,200); this.setTitle("自作のフレーム"); } ・・・ これにより、フレームが生成されるときに、その大きさとフレームタイトルが設定される。 コンストラクタはインスタンス(オブジェクト)が生成される時に呼び出される特別なメソッド
フレームの終了処理 ×を選択した場合 メソッドの上書き→終了処理を加える。 プログラムを終了させる。 //ウィンドウが閉じられたときに終了するようにオーバーライド protected void processWindowEvent(WindowEvent e) { if (e.getID() == WindowEvent.WINDOW_CLOSING) { System.exit(0); } ×を選択した場合 プログラムを終了させる。 メソッドの上書き→終了処理を加える。