9 オブジェクト指向プログラミング ソフトウェア工学 OBJECT-ORIENTED PROGRAMMING

Slides:



Advertisements
Similar presentations
アルゴリズムとプログラミン グ (Algorithms and Programming) 第6回:クラスとインスタンス クラスの宣言 アクセス修飾子 インスタンスの生成 (new キーワード) this キーワード フィールドとメソッドの実際の定義と使い 方 クラスの宣言 アクセス修飾子 インスタンスの生成.
Advertisements

オブジェクト指向 言語 論 第八回 知能情報学部 新田直也. 多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println(
AIプログラミング Java とオブジェクト指向プログラミングの基 礎 認知システム論 情報工学コース コンピュータサイエンスコース 生体情報コース.
ソフトウェア工学 理工学部 情報システム工学科 新田直也. 演習問題 1 の解答例  入庫処理の DFD 酒屋の在庫問題の DFD( 入庫処理 ) 更新情報 在庫ファイル 更新処理 倉庫係 在庫不足リスト 在庫ファイル 出庫指示書 新規出庫 判定 出庫指示書 作成処理 出庫依頼 積荷票.
ソフトウェア工学 知能情報学部 新田直也. オブジェクト指向パラダイムと は  オブジェクト指向言語の発展に伴って形成され てきたソフトウェア開発上の概念.オブジェク ト指向分析,オブジェクト指向設計など,プロ グラミング以外の工程でも用いられる.  ソフトウェアを処理や関数ではなくオブジェク.
6.4継承とメソッド 6.5継承とコンストラクタ 11月28日 時田 陽一
プログラミング演習II 2004年11月 30日(第6回) 理学部数学科・木村巌.
Android と iPhone (仮題) 情報社会とコンピュータ 第13回
プログラミング基礎I(再) 山元進.
~手続き指向からオブジェクト指向へ(Ⅰ)~
プログラミング基礎I(再) 山元進.
プログラミングパラダイム さまざまな計算のモデルにもとづく、 プログラミングの方法論 手続き型 関数型 オブジェクト指向 代数 幾何.
アルゴリズムとデータ構造1 2007年6月12日
アルゴリズムとプログラミング (Algorithms and Programming)
実行時のメモリ構造(1) Jasminの基礎とフレーム内動作
Javaのインタフェース についての補足 2006年5月17日 海谷 治彦.
オブジェクト指向プログラミング(2) OOPの三大要素 「クラス」「ポリモーフィズム」「継承」
アルゴリズムとプログラミング (Algorithms and Programming)
社会人学習講座 「Javaプログラミング概論」
プログラミング演習Ⅰ 課題2 10進数と2進数 2回目.
計算機プログラミングI 第8回 2002年12月5日(木) メソッドとクラス (教科書6章) クイズ インスタンスメソッド インスタンス変数
Javaとオブジェクト指向プログラミングの基礎
第6回独習Javaゼミ 第6章 セクション4~6 発表者 直江 宗紀.
プログラミング演習3 第2回 GUIの復習.
細かい粒度でコードの再利用を可能とするメソッド内メソッドのJava言語への導入
オブジェクト指向 プログラミング 第十四回 知能情報学部 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
プログラミング言語入門 手続き型言語としてのJava
アルゴリズムとプログラミング (Algorithms and Programming)
細かい粒度で コードの再利用を可能とする メソッド内メソッドと その効率の良い実装方法の提案
独習JAVA 6.8 コンストラクタの修飾子 6.9 メソッドの修飾子 6.10 ObjectクラスとClassクラス 11月28日(金)
オブジェクト指向 プログラミング 第十一回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
暗黙的に型付けされる構造体の Java言語への導入
プログラミング言語入門.
オブジェクト指向 プログラミング 第十四回 知能情報学部 新田直也.
プログラミング演習3 第2回 GUIの復習.
11 ソフトウェア工学 Software Engineering デザインパターン DESIGN PATTERNS.
復習 前回の関数のまとめ(1) 関数はmain()関数または他の関数から呼び出されて実行される.
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
C#言語ソースプログラムの原型 C言語 C#言語 Hello World! Hello Students! オマジナイ! 適当なクラス名
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第八回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十ニ回 知能情報学部 新田直也.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト プログラミング 第2回 プログラムの基本.
アルゴリズムとプログラミング (Algorithms and Programming)
オブジェクト指向 プログラミング 第九回 知能情報学部 新田直也.
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
C#プログラミング実習 第3回.
計算機プログラミングI 木曜日 1時限・5時限 担当: 増原英彦 第1回 2002年10月10日(木)
アルゴリズムとプログラミング (Algorithms and Programming)
サブゼミ第7回 実装編① オブジェクト型とキャスト.
第5回 プログラミングⅡ 第5回
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
JAVA入門⑥ クラスとインスタンス.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
情報処理Ⅱ 小テスト 2005年2月1日(火).
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
オブジェクト指向言語論 第十回 知能情報学部 新田直也.
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
Presentation transcript:

9 オブジェクト指向プログラミング ソフトウェア工学 OBJECT-ORIENTED PROGRAMMING Software Engineering オブジェクト指向プログラミング OBJECT-ORIENTED PROGRAMMING オブジェクト指向プログラミングの考え方とその3大特徴およびJava言語によるプログラムの記述例を学ぶ.Javaはインターネットなどと連携した現代的なプログラムを記述するのに適した実用的なプログラミング言語である.ただし,この講義はJavaを修得してもらうことを目的としているわけではないので,Javaの細部は理解できなくてもかまわない.オブジェクト指向の概念と3つの特徴を理解してほしい.

構成 Part1 オブジェクト指向の基本概念 Part2 オブジェクト指向の3大特徴 1 カプセル化 2 継承(インヘリタンス) 1 カプセル化 2 継承(インヘリタンス) 3 ポリモーフィズム(多相性)  今回の授業では,オブジェクト指向プログラミングの最も特徴的な考え方を学ぶ.  具体的なプログラミングはJavaを用いるが,Javaの詳細を学ぶことが目的ではない.  Part1でオブジェクト指向の基本概念を説明した後,Part2でオブジェクト指向の3大特徴を学ぶ.

Part1 オブジェクト指向の基本概念

オブジェクトとは? データと操作をカプセル化した「もの」 X 軸方向 のみに進むロボット カプセル化 位 置 データ(フィールド) 速 度 燃 料 メンバ どこ?  オブジェクト(object)とは何か? その答えを短く言うと,「データと操作をカプセル化したもの」となる.とはいえ,それで内容が理解できるとは思えないので,順を追って内容を見ていく.  この授業では,このスライドに表示されているようなロボットを動かすプログラムを考える.このロボットが「オブジェクト」のつもりである.  このロボットはx軸上を進むものである.ロボットの状態は,現在の「位置」,現在の「速度」,現在の「燃料」の3つのデータで表すことができる.それらのデータはロボットの胸のあたりにあるメモリーに内蔵されている.  また,このロボットはリモコンの3つの操作を受け付ける.  1つめの操作は,「どこ?」というボタンを押すことで,現在位置(x座標の値)を返してくれる.(それは,たとえば,リモコンの表示画面に表示される.)  2つめの操作は,「変速」というボタンを押して,速度を設定できる.実際には,このボタンを押すほかに,さらに設定すべき新しい速度の値を補助情報として入力する必要がある.  3つめの操作は,「進め」ボタンで,これを押すと,1秒間だけ,現在の設定速度でロボットが前進する.  リモコンからのこれらの指示を実行するためのプログラムがロボットの足のあたりに内蔵されている.  オブジェクト指向プログラミングの用語では,いま述べた「データ」のことを「フィールド」(field) , 「操作」のことを「メソッド」(method)という.「フィールド」と「メソッド」を総称して「メンバ」(member)ということもある.一般的なプログラミング用語で言えば,フィールドは変数,メソッドは関数のようなもので,いずれもデジタルなデータあるいは機械語コードで表現できる.それらが,このロボットという「オブジェクト」の中にまとめて閉じこめられている様子を「カプセル化」(encapsulation)というのだが,もっと正確な説明は後にわかってくる.  重要なのは,「オブジェクト」というのは単なる概念ではなく,これらのデジタルなデータまたはコードからなり,コンピュータのメモリの一定領域を占める具体的な「実体」だということである.この「実体」あるいは「もの」が英語のobjectという単語の意味である. 変 速 操作(メソッド) 進 め

メモリ内に オブジェクトがうようよできる 5 +1 10 8 -1 -4 2 位置 速度 燃料 進 め どこ? 変速 進 め どこ? 変 速 進 め どこ? 変 速 位置 速度 燃料  「オブジェクト」は一定の実メモリ領域を占める「もの」であるが,ふつう,オブジェクト指向でプログラムを書くと,そのようなオブジェクトがたくさん生成される.それぞれのオブジェクトごとにメモリ領域が占められる.  ロボットの場合には,このスライドのように,状態(各フィールド「位置」,「速度」,「燃料」のそれぞれの値)の異なるロボットが生成されるわけである.  ただし,操作(メソッド)を表すプログラムコードはこれらのオブジェクトに共通である.

いろんな種類(クラス)の オブジェクトが共存する 7 2 4 8 1 6 2 3 1 ロボット クラス  オブジェクトにはいろいろな種類のものがあってよい.  たとえば,オブジェクト指向で書かれたあるコンピュータゲームの中では,ロボットのほかに船が出てきて,ロボットが船に乗って,いろいろな島に渡って冒険をするのかもしれない.この場合,「ロボット」と「船」は異なる種類のオブジェクトである.  オブジェクトの種類のことを「クラス」(class)という.この例の場合,ロボットクラス,船クラスという2つのクラスのオブジェクトが存在することになる. 船 クラス

オブジェクトはクラス(ひな形)から 生成されるインスタンス(実例) 6 2 9 5 4 クラス 位 置 速 度 燃料 どこ? 変速 進 め インスタンス 2 3 4  オブジェクト指向プログラミングで初心者が最初につまづく点は,「クラス」と「インスタンス」の区別である.  クラス(class)とは,オブジェクトを作るための「ひな形」あるいは「設計図」のようなものである.ロボットの例の場合,「位置」,「速度」,「燃料」というフィールドがあることがこの設計図に書かれている.しかし,当然だが,その「現在の値」というのはない.  一方,インスタンス(instance)とは,この設計図から作られた「実例」のことであり,各フィールドには「現在の値」が記録されている.このスライドでは,1つのクラスから異なる3つのインスタンスが生成されている.これまで出てきた「オブジェクト」という言葉は,この「インスタンス」と同じ意味である.  メソッドの具体的なコードもクラスに記述されている.このクラスからインスタンスを生成すると,各インスタンスにはこれらのメソッドがそのままコピーされる.(ただし,これは概念上の話で,実際には,1台のコンピュータ内に同じものをたくさんコピーしておくのは無駄が多いので,ポインタなどを用いて効率的に実装されている.)  以上の結果,操作(メソッド)はクラスで共通に使用され,データ(フィールド)はインスタンス毎に異なるものとして使われることになる. 操作(メソッド)は クラスで共通 データ(フィールド)は インスタンス毎

Javaではクラスを記述する (ロボットになったつもりで書く) class ロボット { int 位置; int 速度;  int 燃料; int どこ?() {    return(位置); }   void 変速(int 新速度) { 速度 = 新速度; クラス名 整数型 フィールド名 メソッド名 戻り値のデータ型 種々の名前には 日本語を使える 値を戻す  このスライドのプログラムが,これまで設計したロボットをJavaで記述したものである.  Javaで記述するものは,実際にはクラスである.ここではクラス名を「ロボット」としている.  フィールドは,他のプログラミング言語(たとえば,C言語)における変数宣言のような形で宣言される.  メソッドは,(C言語における)関数定義のような形で定義される.  ロボットメソッドのプログラムを書くときのコツは,自分自身がロボットになったつもりで書くことである.  「どこ?」メソッドは,自分が「どこ?」と質問されたつもりで考えて,戻り値として,現在位置の値を返すことにする.  「変速」メソッドは,指定された「新速度」の値に変えよと命令されたつもりになって,自分自身の状態変数である「速度」に,外部から指定された「新速度」の値を保存する. 戻り値 なし 続く 

Javaではクラスを記述する(続き) class ロボット { int 位置; int 速度; int 燃料; 再掲 //---------------------- int 進め() {   if (燃料 > 0) {    位置 = 位置 + 速度;    燃料 = 燃料 - 1;    return 0; } else {    return (-1); } 再掲  「進め」メソッドは,自分が「進め」と命令されたらどうするかを考えて書く.ここでは,現在設定されている速度で1単位時間だけ前進し,燃料が1単位消費される.その結果,「位置」と「燃料」の値が更新される.この場合,正常終了したので,エラーコードとして戻り値0を返すような設計としてある.  燃料が0なら,進むことはできず,エラーコードとして-1を返すことにした. 続く

コンストラクタも記述する class ロボット { int 位置; int 速度; int 燃料; 再掲 //---------------------- ロボット(int p, int v, int f) { 位置 = p; 速度 = v; 燃料 = f; } 再掲 インスタンス生成時 フィールドを初期化 クラス定義の終わり  ロボットのインスタンスが生成されたときに,そのフィールドを初期化するなどのために,コンストラクタ(constructor)という特別なメソッドを定義しておく.  Javaでは,コンストラクタの名前はクラス名と同じにするという約束になっている.  したがって,このスライドでは,「ロボット」というコンストラクタを定義している.この定義の内容は,ロボットのインスタンス生成時にプログラマから引数として渡される p, v, f という3つの整数値を,それぞれ,「位置」,「速度」,「燃料」の3つのフィールドの現在値(初期値)として記録(代入)することを表している.(p, v, f は,position, velocity, fuelの頭文字.)  これが典型的なコンストラクタの定義である.すなわち,引数で与えられたデータをフィールド(状態)の初期値として記録するのである. Constructor

ロボットを生成し,使用する (ロボットのコントローラを持ったつもりで書く) public class ロボットのテスト { public static void main(String args[]) { ロボット robocop = new ロボット(0,1,10); robocop.進め(); robocop.変速(2); while(robocop.どこ?() < 10) { } ローカル変数宣言 ロボット生成 (コンストラクタ呼出し)  これはロボットを使う簡単なプログラムである.ロボットを使うプログラムを書くときのコツは,自分がロボットのコントローラを持ったつもりで,いろいろなボタンを押しまくるように書く.ここで比喩的に言っている「ボタンを押す」とは,すでに定義した3つの「メソッドを呼び出す」ことである.  オブジェクト(インスタンス)は,new というキーワードの後にコンストラクタを呼び出す形式で生成する.この例では,new ロボット(...)によって,ロボットのインスタンスを生成し,コンストラクタの記述にしたがって,位置=0,速度=1,燃料=10に設定している.そのロボットを robocop と名付ける.これは robocop という変数を「ロボット型」と宣言し,その変数の初期値として,いま生成されたロボット(への参照(ポインタ))を代入することである.  Javaでは,オブジェクト.メソッド名(引数, ... ,引数)の形の式を書くことによって,オブジェクトのメソッドを引数を指定して呼び出す(実行する)ことができる.このプログラムでは,Robocop.進め() によって1秒だけロボットを進ませ,つぎに Robocop.変速(2) によって速度を2に変える.つぎに while ループの中で,rococo.どこ?( ) によって現在位置を取得し,それが10未満である間,ループの中で進めボタンを連打する.現在位置が10以上になった時点でプログラムは停止する.このようにして,ロボットクラスで定義された3つのメソッド「進め」,「変速」,「どこ?」を(コントローラーのボタンを押しているかのように)適切に呼び出しながらロボットを動かすプログラムである.  プログラミングの際には,ロボットを作る「メーカー」と,ロボットを買って動かす「ユーザ-」との区別が大事である.メーカーは,ロボットを動かす汎用的なソフトウェア部品をクラスとして制作する.そのプログラムは自分がロボットになったつもりで書く.それに対してユーザーは,自分の応用目的に応じて,アプリケーションを制作する.そのプログラムは自分がロボットのコントローラーを持ったつもりで書く. ロボットを使う (メソッド呼出し)

Part2 オブジェクト指向の3大特徴 1 カプセル化 2 継承(インヘリタンス) 3 ポリモーフィズム(多相性) 1 カプセル化 2 継承(インヘリタンス) 3 ポリモーフィズム(多相性) オブジェクト指向プログラミングにはさまざまな特徴があるが,このスライドに示したものが,もっとも大きな3つの特徴と考えられている.それぞれを見ていこう.

特徴1:カプセル化 (encapsulation) 1 カプセル化 2 継承(インヘリタンス) 3 ポリモーフィズム(多相性)

いろんなクラスが出てきたら... 制作者B 船 クラス アクセス不可 使用可 カプセル化 制作者A ロボット クラス 船のフィールドの宣言 船のメソッドの宣言 船 クラス 制作者B 使用可 アクセス不可 カプセル化 カプセル(殻) の硬さも重要 制作者A ロボット クラス  制作者Aがロボットクラスをプログラムし,制作者Bが船クラスをプログラムしているとしよう.これらのプログラムは最終的に1つの計算機の同一メモリ内で実行されるので,2人の制作者は連絡を密にして注意深くプログラムを作らないと思わぬミスを生むことがある.たとえば,制作者Bが,船のメソッドの中でロボットのフィールドの値を勝手に変更するプログラムを書くと,ロボットが制作者Aの思わぬ状態変化をして,大変都合が悪い.  そのため,オブジェクト指向の考え方では,基本的に,1つのクラスの中のプログラムが,他のクラスのフィールドの値を直接読み書きすることを禁じている.そのかわり,メソッドの呼び出しを通して,フィールドにアクセスできるようにする.(「読み書き」をまとめて「アクセス」という.)これにより,意図しないプログラムの動作を防止して,バグ(誤り)の生成を抑制し,セキュリティを高めている.  つまり,各クラスはある種の殻によって,内部へのアクセス方法を制限している.あるいは,内部のフィールドを保護している.この機能を「カプセル化」と呼ぶ.このスライドの太いピンク色の部分が殻(あるいはカプセル)のつもりである.カプセルの殻の中にフィールドとメソッドが閉じ込められている.この殻の固さは,ほかのクラスのプログラムが内部のフィールド に直接アクセスすることを防御できる程度に固い.しかし,ほかのクラスのプログラムが自分のメソッドを呼び出すことを許す程度に柔らかい.カプセルという言葉で,薬が思い浮ぶ.子供などが粉薬(こなぐすり)を飲みやすくするために,オブラートでできているカプセルに入れることがある.カプセルを飲み込むと,カプセルは胃の中で解け,中の薬が胃の中に出てきて吸収される.このカプセルの固さにも注意が必要である.飲むときに破れて口の中に薬がこぼれてしまわない程度に固い必要がある.しかし,胃の中で溶ける程度には柔らかくなければならない.このように,カプセル化は,オブジェクトの内部情報へのアクセスを,適切なレベル(殻の硬さ)で保護している. ロボットのフィールドの宣言 ロボットのメソッドの宣言

カプセル化 メソッドを通してのみ,フィールドにアクセス .メソッド名(引数, ... , 引数) フィールド メソッド  「オブジェクトのフィールドには,メソッドを通してのみアクセスできる」という概念を図にすると,このスライドのような感じとなる.ちょうど,フィールドがたまごの黄身で,メソッドがその白身であるかのように,フィールドはメソッドによって周囲を囲まれ,守られている.そのため,フィールドの中味にオブジェクトの外部から直接アクセスすることができない.  フィールドにアクセスするには,    オブジェクト.メソッド名(引数, ... ,引数) の形のプログラムコードを書いて,オブジェクト内のメソッドを起動するしかない.このスライドの図は,このプログラムコードの文法に似せて描いてある. オブジェクトとは,データと操作をカプセル化した「もの」

ゲッター,セッター,コンストラクタ は超基本メソッド class Robot { int position; int getPosition() {    return(position); }   void setPosition(int p) {    position = p; Robot(int p) { position = p; } Getter 値を取得 Setter 値を設定 ローカル変数 寿命が短い  最も基本的なメソッドは,ゲッター(getter), セッター(setter), コンストラクタ(constructor)である.  ゲッターは,値を読み取る(ゲットする)ためのメソッドである.サッカーなどのスポーツでたくさん点を取る人を point getterというが,それと同じ単語である.ゲッターには,慣習的に,getの後ろにフィールド名を付加した名前を付けることが多い.このスライドのプログラム例の場合,position というフィールドのゲッターは getPosition と命名されている.  セッターは,値を書き込む(セットする,設定する)ためのメソッドである.バレーボールでも,トスを上げてアタックする準備を設定する選手をsetterという.セッターには,慣習的に,setの後ろにフィールド名を付加した名前を付けることが多い.この例の場合,position というフィールドのセッターは setPosition と命名されている.この例では,setPositionの引数で与えられた整数をローカル変数 p で受け取り,セッターのプログラム本体で,それをフィールドposition に代入している.ローカル変数 p は,メソッドの実行が終了したら消えてしまうような,寿命が短い変数である.それに対して,フィールドposition は,オブジェクトが存在している限り共に存在するような長い寿命を持っている.セッターを用いて,暫定的なデータをフィールドに保存することによって,オブジェクトの状態が変更されることになる.  コンストラクタは,すでに見たように,インスタンス生成時の初期設定を定義している.コンストラクタの名前はクラス名と同じでなければならない.オブジェクトを新規に生成して,コンストラクタを呼び出してフィールドを初期化するには, new コンストラクタ(引数, … ,引数) という形式を用いる. Constructor 値を初期化

ゲッター,セッターを通してフィールドにアクセス メソッド アクセス getPosition( ) setPosition( p ) Position .setPosition(10) Robot( p )  この例では,Position の値を10にセットするために,setPositionというセッターを使用している.

クラス図 (API: Application Programmer's Interface) クラス名 Robot int position Robot(int p) int getPosition() void setPosition(int p) フィールド メンバ メソッド  いつもクラスを定義したJavaのソースコードを見るのは大変なので,設計内容の概略をこのようなクラス図として図式化することが多い.長方形を3段に分け,最上段にはクラス名を,中段にはフィールド名(とそのデータ型名)を,最下段にはメソッド名(と引数及び戻り値のデータ型名)を記入する.  このような情報は,クラスを利用して応用プログラムを作成しようとするプログラマーに対して,利用法の「インタフェース」(ソフトウェア部品の使い方)を提供しているので,API (Application Programmer's Interface)と呼ばれることがある.

ロボットのクラス図 ロボット int 位置 int 速度 int 燃料 コンストラクタ ロボット(int p, int v, int f ) void 変速(int 新速度) int 進め( ) ゲッター  これはこれまで作ってきた「ロボット」クラスのクラス図である.  「どこ?」メソッドはゲッター,「変速」メソッドは セッターになっている.  「進め」メソッドはゲッター, セッターのような基本的なメソッドではなく,このロボット特有の応用的なメソッドである. セッター オペレータ (一般のメソッド)

特徴2:継承(インヘリタンス) (inheritance) 1 カプセル化 2 継承(インヘリタンス) 3 ポリモーフィズム(多相性)

継承(インヘリタンス) 親を再利用して子を作る 親 子 親 子 継承(インヘリタンス) 親を再利用して子を作る 位置 速度 燃料 進め どこ? 変速 使い捨ての ロボット 位置 速度 燃料 進め どこ? 変速 容量 補給 再利用可能 ロボット 新操作 新データ  オブジェクト指向の特徴は,すでに作ったコードを再利用して機能拡張をしていく仕組みが整っていることである.それが継承(インヘリタンス)という機能である.  この例では,これまで作成した(使い捨ての)ロボットを拡張して,再利用可能なロボットを作ろうとしている.つまり,燃料が切れたら,燃料補給できる機能を追加する.  新しいフィールドとして,燃料タンクの「容量」を追加する.  新しいメソッドとして,「補給」メソッドを追加する.  このようなクラス間の関係を,図のように,親/子と呼んだり,スーパークラス/サブクラスと呼んだりする.「ものつくり」の観点から言えば,スーパークラス(親クラス)は部品であり,ソフトウェア部品メーカーが供給することもある.それを目的に合わせてユーザ側のプログラマーがカスタマイズしたり機能拡張するなど,有効に再利用して作るものがサブクラス(子クラス)である. スーパー クラス サブ

サブクラスの定義 新属性,新機能,新コンストラクタのみ記述 新データ class 再利用可能ロボット extends ロボット{ int 容量;   void 補給() { 燃料 = 容量; }   再利用可能ロボット(int p, int v, int f, int c) { super(p, v, f); 容量 = c; 新操作 スーパークラスの指定 新コンストラクタ  Javaではこの図のように extends 親クラス名 と書くことによって,親クラスを再利用して子クラスを定義できる.この例では,すでに作成した「ロボット」クラスを親クラスとし,その子クラスとして「再利用可能ロボット」クラスを定義している.  子クラスには,新しく追加するフィールドやメソッドだけを記述する.すでに親クラスで定義してあるフィールドやメソッドは,書かなくても,あたかも書いてあるかのように,子クラスに引き継がれる.  また,この子クラスをコンパイルする際には,スーパークラスを書き直したり,再コンパイルする必要はない.さらに重要なのは,スーパークラスのソースコード(ソースファイル)は無くてよく,そのコンパイルされたコード(クラスファイル)さえあればOKである.これは特にスーパークラスが商用で,価格のある商品の場合に重要である.スーパークラスを作成したソフトウェアメーカーは,それを販売するにあたって,ふつうはソースコードを公開したくない.公開すれば他社等に設計情報を知られるからである.Javaの場合,スーパークラスを購入したユーザーは,APIだけを知っていれば,ソースファイルがなくても,クラスファイルさえあれば,購入したスーパークラスを部品として利用し,子クラスを自分で定義できるのである. スーパークラスを 書き直したり 再コンパイルする 必要はない

継承のクラス図 ロボット int 位置 int 速度 int 燃料 int どこ?( ) void 変速(int 速度) int 進め( ) スーパークラス  クラス図を書くときには,子クラスから親クラスに矢印を付けておく. 再利用可能ロボット int 容量 void 補給( )

継承の使用例 public class 再利用可能ロボットのテスト { public static void main(String args[]) { 再利用可能ロボット robo2 = new 再利用可能ロボット(0,1,10,10); for (int i=0; i<100; i=i+1) { if(robo2.進め()< 0) { robo2.補給(); robo2.進め(); }   } 進め( ) は,  正常に進めたら0,  燃料切れだったら-1 を返す.  再利用可能ロボットを使ってみよう.この例では,再利用可能ロボット robo2を生成し,forループを使って「進め」ボタンを100回連打する.ただし,途中で燃料切れになったときは,「進め」メソッドは負のエラーコードを返すので,燃料を補給して,ボタンを1回押し直している. 新しいメソッドの使用 継承されたメソッドの使用

特徴3:ポリモーフィズム(多相性) (polymorphism) 1 カプセル化 2 継承(インヘリタンス) 3 ポリモーフィズム(多相性)

ポリモーフィズム(多相性) 同じメッセージでもクラスによって処理が異なる   ポリモーフィズム(多相性) 同じメッセージでもクラスによって処理が異なる 進め ロボットクラス .進め( ) 授業を 進める 先生クラス 進め .進め( ) メッセージ  このスライドに図示してある3つのクラス(ロボット,船,先生)に,いずれも「進め」メソッドがあるとしよう.3つのメソッドの内容(プログラムコード)は全く異なるものである.ロボットが「進む」とは,足を動かすプログラムコードを実行することだし,船が「進む」とは,スクリューを回転させるコードを実行することである.先生が「進む」とは,脱線していた授業を進ませることである.したがって,本来なら異なるメソッド名を付けるのがスジである.  しかし,人間にとって「進め」という言葉が適切なら,その言葉を共通に使えるようにした方が便利である.言葉の数の節約になり,人間にとって心理的に覚えやすい.  プログラミングの世界でその考え方を採り入れたのが「ポリモーフィズム」という機能である.(このスライドでは「多相性」という和訳を採用したが,「多態性」,「多様性」などと呼ばれるときもある.カタカナ書きでも,「ポリモフィズム」,「ポリモルフィズム」などの表記が使われることがある.)  オブジェクト指向の言葉で述べると,「同じメッセージ(メソッド)でも,受け手のオブジェクトのクラスによって,処理(意味)が異なる」という機能である.ここで「同じメソッド」と言っているのは,一般には,メソッドの名前が同じであることに加えて,そのインタフェース(すなわち,引数の数と型,およびメソッドからの戻り値の型)までも同じであることを指している. 進め 船クラス .進め( )

型の階層(包含) 進めるもの 型 ロボット 型 船 型 先生 型 進め 進め 進め  「ロボット」クラスのオブジェクトは「ロボット」型というデータ型である.同様に,「船」クラスは「船」型,「先生」クラスは「先生」型である.これらのクラス(データ型)は,共通に「進め」という同一の名前をもつメソッドをもっている.  そのような共通性を認識して,これらの複数のデータ型をまとめて,1つのデータ型として総称的に定義することができる.このスライドの例ではそれを「進めるもの」という名前のデータ型としている.

「進めるもの」のインタフェース interface 進めるもの { int 進め(); } 抽象メソッド  Javaでこの考え方を実現する方法の1つが,「インタフェース」という機能である.その書き方はクラスの書き方と似ているが,class のかわりに interface というキーワードを用いる点が異なる.最も重要な違いは,メソッドの本体({ と }で囲まれて記述されるプログラムコード)を書くことが許されない点である.そのようなメソッドを抽象メソッドという.  このJavaコードの例は,「進めるもの」は,    int 進め(); というメソッドを共通に持っていることを宣言している.  Javaで良く使われるインタフェースとして,Runnable インタフェースというのがある.これは,runメソッドを持つクラスを総称するためのもので,実際にはつぎのように定義されている.  interface Runnable { void run( ); }

「進めるもの」の実装 ここを追加する class ロボット implements 進めるもの{ int 位置; int 速度; int 燃料; int どこ?() { return(位置); } void 変速(int 新速度) { 速度 = 新速度; } int 進め() {   if (燃料 > 0) {    位置 = 位置 + 速度;    燃料 = 燃料 - 1;    return 0; } else {    return (-1); }  ロボット型が,進めるもの型に含まれることを,implements というキーワードを用いてこのスライドのように記述する.  このような場合,「ロボット」クラスは「進めるもの」インタフェースを「実装している」という.Javaの約束によって,インタフェースを実装するクラスの中では,そのインタフェース内で記述された抽象メソッドの本体を具体的に記述する必要がある.この例の場合,「進めるもの」インタフェースには,int 進め( ) という抽象メソッドが記述されていたことを思い出そう.したがって,「進めるもの」インタフェースを実装する「ロボット」クラスの中で,int 進め( ) メソッドの本体が具体的に記述されている.

実装のクラス図 実装 interface 進めるもの int 進め( ) ロボット int 位置 int 速度 int 燃料  ロボットが「進めるもの」を実装していることを,破線の矢印を使って,このようなクラス図で表す. int どこ?( ) void 変速(int 速度) int 進め( )

ポリモーフィズムの使用例 いろいろな「進めるもの」を統一的に進ませる 進めるもの[] A = new 進めるもの[3]; A[0] = new ロボット(0,1,10); A[1] = new 船("横浜"); A[2] = new 先生("数学","舞黒素太"); 配列 1 2 進め 進め 進め  ポリモーフィズムが便利と感じるようなプログラムの例を紹介しておこう.それは同じインタフェースが実装されたいろいろなクラスのオブジェクトを一次元配列に記憶しておき,それらに対して同じメッセージを送る(同じ名前のメソッドを実行する)ことにより,各オブジェクト特有の適切な動作を統一的なコーディングによって起こさせる例である.  Java で整数(int)の一次元配列を作るには,つぎの例のようにする. int [ ] a = new int[n]; または  int a[ ] = new int[n];  これは,n個の要素 a[0],a[1],...,a[n-1] をもつint型の配列を生成し,a という名前の変数に代入している例である.int 型以外の配列を作るときには,型の名前を int でない適切なものに変えればよい.  このスライドのプログラムでは,「進めるもの」型のオブジェクトを3つまで記憶できる配列を用意して,Aという名前の変数に代入している.プログラムの第2~4行目では,Aの3つの要素に,それぞれ,ロボット,船,先生のインスタンスを記憶させている.   そもそもポリモーフィズムがなければ,こういうことはできない.なぜなら,配列というものは,同じデータ型のデータを複数個記憶するためのデータ構造だからである.たとえば,整数型や実数型や文字列型のデータを混在させて記憶することはできない.  しかし,ポリモーフィズムがあればそれができる.この例では,ロボット,船,先生は異なるデータ型で,ふつうは同じ配列に混在させることはできないのだが,それらの3つのデータ型を包含する「進めるもの」型の配列を導入することにより,すべてを記憶できるようになる.なぜなら,ロボットも船も先生も「進めるもの」型という同じデータ型に属するからである.

ポリモーフィズムの使用例(続き) いろいろな「進めるもの」を統一的に進ませる 進めるもの A[] = new 進めるもの[3]; A[0] = new ロボット(0,1,10); A[1] = new 船("横浜"); A[2] = new 先生("数学","舞黒素太"); for(i=0; i<3; i++) A[i].進め(); 配列 1 2  さて,つぎに進もう.ここが山場である.前のコードに続いて,このスライドでは for 文が書かれている.for ループの中で,i を0,1,2というふうに変化させながら,ループの本体 A[i].進め( ); が3回実行されるのだが,そこでは「進め」という同じ名前のメソッドによって,異なる意味と異なるメカニズムのもとで A[ i ] に記憶されているオブジェクトが「進む」こととなる.すなわち,ループの第1周目(i=0)ではロボットが足を動かしながら進み,第2周目では船がスクリューを回転させて進み,第3周目では先生が授業を進めるというバラエティに富んだ処理が行われる.要するに,全員に一斉に「進め」という指示を与えたときに,各自がそれぞれの「進め」の意味に従って行動する様子が表現できているのである.  このような処理を簡潔な1行で記述できるのは大変便利である.ポリモーフィズムがなければ,オブジェクトがどのクラスのインスタンスなのかの判別に instanceof というJavaの機能を用いて,if 文を使って,    for( i=0; i<3; i++) if (A[i] instanceof ロボット) A[i].ロボット進め( ) else if (A[i] instanceof 船) A[i].船進め( ) else if (A[i] instanceof 先生) A[i].先生進め( ); のように,インスタンスのクラスが何であるかに応じて,「ロボット進め」,「船進め」,「先生進め」という,名前の異なるメソッドを実行させることになる.その程度のことはたいした面倒なことではないのだが,プログラムのバージョンアップのときに「進め」を実行できる第4,第5のクラスが導入されてくるとその違いが明確になる.ポリモーフィズムがあるときは,第4,第5のクラスをこれまでのように定義すればそれで済み,このスライドの forループのプログラムを書き直す必要はない.しかし,if 文を使うプログラムでは,if 文の条件判定を新クラス向けに追加しなければならないので,このfor文を書き直し,再コンパイルする必要が生ずるのである.ましてや,メーカーがソースコードを公開していない場合,末端のユーザー(アプリケーションプログラマ)には,このバージョンアップの作成は不可能になってしまう.  このようなプログラミングテクニックは Java のプログラムコードでたくさん見かけるものなので,ぜひ覚えておこう.良く知られているものは,Runnableインタフェースである.Javaでは,「アニメーションを動かすと同時に,GUIのクリックも受け付ける」などのように,複数のプログラムを同時に動かすときには,スレッド(Thread)と呼ばれるオブジェクトを使う.その場合,プログラマは,応用に合わせて,オブジェクトに void run( ) というメソッドを記述しておく必要がある.この run ( )メソッドはJavaが事前に用意している Runnableというインタフェースの中で記述された抽象メソッドである.プログラマは,Runnableインタフェースを実装するようなクラスを自分で定義し,その中でrun ( )メソッドの中身を具体的に記述できる.つまり,先ほどの説明と比較すると,「進め」メソッドが run ,「進めるもの」インタフェースが Runnable に対応している. 進め 進め 進め

オブジェクト指向のまとめ 基本用語 オブジェクト,フィールド,メソッド,メンバ クラス,インスタンス ゲッター,セッター,コンストラクタ スーパークラス,サブクラス,クラス図 インタフェース,抽象メソッド,実装 特徴 1 カプセル化 2 継承(インヘリタンス) 3 ポリモーフィズム(多相性)  このスライドでまとめた用語のおよそのイメージが,それぞれ数秒で想起されるように復習してね.

演習問題 9 オブジェクト指向プログラミングのもつ3つの大きな特徴について説明しなさい.字数は全体で400字程度とする.