オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/se/09-object.pdf ·...

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

Upload: others

Post on 13-Sep-2019

10 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

1

オブジェクト指向プログラミング

OBJECT-ORIENTED PROGRAMMING

9 ソフトウェア工学Software Engineering

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

Page 2: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

2

構成

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

Part2 オブジェクト指向の3大特徴

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

今回の授業では,オブジェクト指向プログラミングの最も特徴的な考え方を学ぶ.

具体的なプログラミングはJavaを用いるが,Javaの詳細を学ぶことが目的ではない.Part1でオブジェクト指向の基本概念を学び,Part2でオブジェクト指向の3大特徴を学ぶ.

Page 3: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

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

3

Page 4: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

4

X軸方向のみに進むロボット

オブジェクトとは?データと操作をカプセル化した「もの」

位 置

速 度

燃 料

データ(フィールド)

進 め

どこ?

変 速

オブジェクト

メンバ

操 作(メソッド)

カプセル化

オブジェクト(object)とは何か? その答えを短く言うと,「データと操作をカプセル化したもの」となる.とはいえ,それで内容が理解できるとは思えないので,順を追って内容を見ていく.

この授業では,このスライドに表示されているようなロボットを動かすプログラムを考える.このロボットが「オブジェクト」のつもりである.

このロボットはx軸上を進むものである.ロボットの状態は,現在の「位置」,現在の「速度」,現在の「燃料」の3つのデータで表すことができる.それらのデータはロボットの胸のあたりにあるメモリーに内蔵されている.

また,このロボットはリモコンの3つの操作を受け付ける.

1つめの操作は,「どこ?」というボタンを押すことで,現在位置(x座標の値)を返してくれる.(それは,たとえば,リモコンの表示画面に表示される.)

2つめの操作は,「変速」というボタンを押して,速度を設定できる.実際には,このボタンを押すほかに,さらに設定すべき新しい速度の値を補助情報として入力する必要がある.

3つめの操作は,「進め」ボタンで,これを押すと,1秒間だけ,現在の設定速度でロボットが前進する.

リモコンからのこれらの指示を実行するためのプログラムがロボットの足のあたりに内蔵されている.

オブジェクト指向プログラミングの用語では,いま述べた「データ」のことを「フィールド」(field) , 「操作」のことを「メソッド」(method)という.「フィールド」と「メソッド」を総称して「メンバ」(member)ということもある.一般的なプログラミング用語で言えば,フィールドは変数,メソッドは関数のようなもので,いずれもデジタルなデータあるいは機械語コードで表現できる.それらが,このロボットという「オブジェクト」の中にまとめて閉じこめられている様子を「カプセル化」(encapsulation)というのだが,もっと正確な説明は後にわかってくる.

重要なのは,「オブジェクト」というのは単なる概念ではなく,これらのデジタルなデータまたはコードからなり,コンピュータのメモリの一定領域を占める具体的な「実体」だということである.この「実体」あるいは「もの」が英語のobjectという単語の意味である.

Page 5: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

5

5

+1

10

進 め

どこ?

変速

メモリ内にオブジェクトがうようよできる

位置

速度

燃料

8

-1

8

進 め

どこ?

変 速

-4

2

0

進 め

どこ?

変 速

「オブジェクト」は一定の実メモリ領域を占める「もの」であるが,ふつう,オブジェクト指向でプログラムを書くと,そのようなオブジェクトがたくさん生成される.それぞれのオブジェクトごとにメモリ領域が占められる.

ロボットの場合には,このスライドのように,状態(各フィールド「位置」,「速度」,「燃料」のそれぞれの値)の異なるロボットが生成されるわけである.

ただし,操作(メソッド)を表すプログラムコードはこれらのオブジェクトに共通である.

Page 6: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

6

船 クラス

ロボット クラス

いろんな種類(クラス)のオブジェクトが共存する

816

724

231

オブジェクトにはいろいろな種類のものがあってよい.

たとえば,オブジェクト指向で書かれたコンピュータゲームの中で,ロボットのほかに船が出てきて,ロボットが船に乗って,いろいろな島に渡って冒険をするのかもしれない.この場合,「ロボット」と「船」は異なる種類のオブジェクトである.

オブジェクトの種類のことを「クラス」(class)という.この例の場合,ロボットクラス,船クラスという2つのクラスのオブジェクトが存在することになる.

Page 7: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

7

オブジェクトはクラス(ひな形)から生成されるインスタンス(実例)

位 置

速 度

燃 料

どこ?

変 速

進 め

234

インスタンスクラス 6

29

254

操作(メソッド)は

クラスで共通

データ(フィールド)は

インスタンス毎に値が違う

オブジェクト指向プログラミングで初心者が最初につまづく点は,「クラス」と「インスタンス」の区別である.

クラス(class)とは,オブジェクトを作るための「ひな形」あるいは「設計図」のようなもの

である.ロボットの例の場合,「位置」,「速度」,「燃料」というフィールドがあることがこの設計図に書かれている.しかし,当然だが,その「現在の値」というのはない.

一方,インスタンス(instance)とは,この設計図から作られた「実例」のことであり,各

フィールドには「現在の値」が記録されている.このスライドでは,1つのクラスから異なる3つのインスタンスが生成されている.これまで出てきた「オブジェクト」という言葉は,この「インスタンス」と同じ意味である.

メソッドの具体的なコードもクラスに記述されている.このクラスからインスタンスを生成すると,各インスタンスにはこれらのメソッドがそのままコピーされる.(ただし,これは概念上の話で,実際には,1台のコンピュータ内に同じものをたくさんコピーしておくのは無駄が多いので,ポインタなどを用いて効率的に実装されている.)

以上の結果,操作(メソッド)はクラスで共通に使用され,データ(フィールド)はインスタンス毎に異なるものとして使われることになる.

Page 8: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

8

Javaではクラスを記述する(ロボットになったつもりで書く)

class ロボット {int 位置;int 速度;int 燃料;

int どこ?() {return(位置);

}

void 変速(int 新速度) {速度 = 新速度;

}続く

クラス名

フィールド名

種々の名前には日本語を使える

メソッド名

整数型

値を戻す

戻り値のデータ型

戻り値なし

このスライドのプログラムが,これまで設計したロボットをJavaで記述したものである.Javaで記述するものは,実際にはクラスである.ここではクラス名を「ロボット」としている.フィールドは,他のプログラミング言語(たとえば,C言語)における変数宣言のような形で宣言される.

メソッドは,(C言語における)関数定義のような形で定義される.ロボットメソッドのプログラムを書くときのコツは,自分自身がロボットになったつもりで書くことである.

「どこ?」メソッドは,自分が「どこ?」と質問されたつもりで考えて,戻り値として,現在位置の値を返すことにする.

「変速」メソッドは,指定された「新速度」の値に変えよと命令されたつもりになって,自分自身の状態変数である「速度」に,外部から指定された「新速度」の値を保存する.

Page 9: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

9

Javaではクラスを記述する(続き)

class ロボット {int 位置;int 速度;int 燃料;

//----------------------int 進め() {

if (燃料 > 0) {位置 = 位置 + 速度;燃料 = 燃料 - 1;return 0;

} else return (-1);

}

再掲

続く

「進め」メソッドは,自分が「進め」と命令されたらどうするかを考えて書く.ここでは,現在設定されている速度で1単位時間だけ前進し,燃料が1単位消費される.その結果,「位置」と「燃料」の値が更新される.この場合,正常終了したので,エラーコードとして戻り値0を返すような設計としてある.

燃料が0なら,進むことはできず,エラーコードとして-1を返すことにした.

Page 10: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

10

コンストラクタも記述するclass ロボット {int 位置;int 速度;int 燃料;

//----------------------ロボット(int p, int v, int f) {

位置 = p;速度 = v;燃料 = f;

}}

再掲

クラス定義の終わり

Constructor

インスタンス生成時フィールドを初期化

ロボットのインスタンスが生成されたときに,そのフィールドを初期化するなどのために,コンストラクタ(constructor)という特別なメソッドを定義しておく.

Javaでは,コンストラクタの名前はクラス名と同じにするという約束になっている.したがって,このスライドでは,「ロボット」というコンストラクタを定義している.この定義の内容は,ロボットのインスタンス生成時にプログラマから引数として渡される p, v, f という3つの整数値を,それぞれ,「位置」,「速度」,「燃料」の3つのフィールドの現在値(初期値)として記録(代入)することを表している.(p, v, f は,position, velocity, fuelの頭文字.)

これが典型的なコンストラクタの定義である.すなわち,引数で与えられたデータをフィールド(状態)の初期値として記録するのである.

Page 11: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

11

ロボットを生成し,使用する(ロボットのコントローラを持ったつもりで書く)

public class ロボットのテスト {public static void main(String args[]){ロボット robocop = new ロボット(0,1,10);

robocop.進め();robocop.変速(2);while(robocop.どこ?() < 10) {robocop.進め();

}}

}

ローカル変数宣言

ロボット生成(コンストラクタ呼出し)

ロボットを使う(メソッド呼出し)

これはロボットを使う簡単なプログラムである.ロボットを使うプログラムを書くときのコツは,自分がロボットのコントローラを持ったつもりで,いろいろなボタンを押しまくるように書く.ここで比喩的に言っている「ボタンを押す」とは,すでに定義した3つの「メソッドを呼び出す」ことである.

オブジェクト(インスタンス)は,new というキーワードの後にコンストラクタを呼び出す形式で生成する.この例では,new ロボット(...)によって,ロボットのインスタンスを生成し,コンストラクタの記述にしたがって,位置=0,速度=1,燃料=10に設定している.そのロボットを robocop と名付ける.これは robocop という変数を「ロボット型」と宣言し,

その変数の初期値として,いま生成されたロボット(への参照(ポインタ))を代入することである.

Javaでは,オブジェクト.メソッド名(引数, ... ,引数)の形の式を書くことによって,

オブジェクトのメソッドを引数を指定して呼び出す(実行する)ことができる.このプログラムでは,robocop.進め() によって1秒だけロボットを進ませ,つぎに robocop.変速(2) によって速度を2に変える.つぎに while ループの中で,robocop.どこ?( ) によって現在位置を取得し,それが10未満である間,ループの中で進めボタンを連打する.現在位置が10以上になった時点でプログラムは停止する.このようにして,ロボットクラスで定義された3つのメソッド「進め」,「変速」,「どこ?」を(コントローラーのボタンを押しているかのように)適切に呼び出しながらロボットを動かすプログラムである.

プログラマーの役割に応じて,ロボットを作る「メーカー」(システムプログラマー)と,ロボットを動かす「ユーザ-」(応用プログラマー)に区別しよう.前者は,ロボットを動かす汎用的なソフトウェア部品をクラスとして制作し,そのプログラムは自分がロボットになったつもりで書く.それに対して後者は,自分の応用目的に応じて,アプリケーションを制作し,そのプログラムは自分がロボットのコントローラーを持ったつもりで書く.

Page 12: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

Part2 オブジェクト指向の3大特徴

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

オブジェクト指向プログラミングにはさまざまな特徴があるが,このスライドに示したものが,もっとも大きな3つの特徴と考えられている.それぞれを見ていこう.

12

Page 13: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

特徴1:カプセル化

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

(encapsulation)

13

Page 14: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

14

船のフィールドの宣言

船のメソッドの宣言

船 クラス制作者B

いろんなクラスが出てきたら…

ロボットのフィールドの宣言

ロボットのメソッドの宣言

ロボット クラス

使用可

アクセス不可

制作者Aカプセル(殻)の硬さも重要

カプセル化

制作者Aがロボットクラスをプログラムし,制作者Bが船クラスをプログラムしているとしよう.これらのプログラムは最終的に1つの計算機の同一メモリ内で実行されるので,2人の制作者は連絡を密にして注意深くプログラムを作らないと思わぬミスを生むことがある.たとえば,制作者Bが,船のメソッドの中でロボットのフィールドの値を勝手に変更するプログラムを書くと,ロボットが制作者Aの思わぬ状態変化をして,大変都合が悪い.そのため,オブジェクト指向の考え方では,基本的に,1つのクラスの中のプログラムが,他のクラスのフィールドの値を直接読み書きすることを禁じている.そのかわり,メソッドの呼び出しを通して,フィールドにアクセスできるようにする.(「読み書き」をまとめて「アクセス」という.)これにより,意図しないプログラムの動作を防止して,バグ(誤り)の生成を抑制し,セキュリティを高めている.

つまり,各クラスはある種の殻によって,内部へのアクセス方法を制限している.あるいは,内部のフィールドを保護している.この機能を「カプセル化」と呼ぶ.このスライドの太いピンク色の部分が殻(あるいはカプセル)のつもりである.カプセルの殻の中にフィールドとメソッドが閉じ込められている.この殻の固さは,ほかのクラスのプログラムが内部のフィールドに直接アクセスすることを防御できる程度に固い.しかし,ほかのクラスのプログラムが自分のメソッドを呼び出すことを許す程度に柔らかい.カプセルという言葉で,薬が思い浮ぶ.子供などが粉薬(こなぐすり)を飲みやすくするために,オブラートでできているカプセルに入れることがある.カプセルを飲み込むと,カプセルは胃の中で解け,中の薬が胃の中に出てきて吸収される.このカプセルの固さにも注意が必要である.飲むときに破れて口の中に薬がこぼれてしまわない程度に固い必要がある.しかし,胃の中で溶ける程度には柔らかくなければならない.このように,カプセル化は,オブジェクトの内部情報へのアクセスを,適切なレベル(殻の硬さ)で保護している.

Page 15: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

15

カプセル化メソッドを通してのみ,フィールドにアクセス

フィールド

メソッド

メソッド

メソッド

メソッド

フィールド

フィールド アクセス

オブジェクトとは,データと操作をカプセル化した「もの」

.メソッド名(引数, ... , 引数)

「オブジェクトのフィールドには,メソッドを通してのみアクセスできる」という概念を図にすると,このスライドのような感じとなる.ちょうど,フィールドがたまごの黄身で,メソッドがその白身であるかのように,フィールドはメソッドによって周囲を囲まれ,守られている.そのため,フィールドの中味にオブジェクトの外部から直接アクセスすることができない.

フィールドにアクセスするには,

オブジェクト.メソッド名(引数, ... ,引数)

の形のプログラムコードを書いて,オブジェクト内のメソッドを起動するしかない.このスライドの図は,このプログラムコードの文法に似せて描いてある.

Page 16: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

16

ゲッター,セッター,コンストラクタは超基本メソッド

class Robot {int position;

int getPosition() {return(position);

}

void setPosition(int p) {position = p;

}

Robot(int p) {position = p;

}}

Getter値を取得

Setter値を設定

Constructor値を初期化

ローカル変数寿命が短い

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

コンストラクタは,すでに見たように,インスタンス生成時の初期設定を定義している.コンストラクタの名前はクラス名と同じでなければならない.オブジェクトを新規に生成して,コンストラクタを呼び出してフィールドを初期化するには, new コンストラクタ(引数, … ,引数) という形式を用いる.

Page 17: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

17

ゲッター,セッターを通してフィールドにアクセス

getP

ositio

n( )

Robot( p )

setP

ositio

n( p

)

メソッド

Positionアクセス

.setPosition(10)

この例では,Position の値を10にセットするために,setPositionというセッターを使用している.

Page 18: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

18

クラス図(API: Application Programmer's Interface)

クラス名

フィールド

メソッド

メンバ

Robot

int position

Robot(int p)int getPosition()void setPosition(int p)

いつもクラスを定義したJavaのソースコードを見るのは大変なので,設計内容の概略をこのようなクラス図として図式化することが多い.長方形を3段に分け,最上段にはクラス名を,中段にはフィールド名(とそのデータ型名)を,最下段にはメソッド名(と引数及び戻り値のデータ型名)を記入する.

このような情報は,クラスを利用して応用プログラムを作成しようとするプログラマーに対して,利用法の「インタフェース」(ソフトウェア部品の使い方)を提供しているので,API (Application Programmer's Interface)と呼ばれることがある.

Page 19: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

19

ロボットのクラス図

ロボット

int 位置int 速度int 燃料

ロボット(int p, int v, int f )int どこ?( )void 変速(int 新速度)int 進め( )

コンストラクタ

ゲッター

セッター

オペレータ(一般のメソッド)

これはこれまで作ってきた「ロボット」クラスのクラス図である.

「どこ?」メソッドはゲッター,「変速」メソッドは セッターになっている.

「進め」メソッドはゲッター, セッターのような基本的なメソッドではなく,このロボット特有の応用的なメソッドである.

Page 20: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

特徴2:継承(インヘリタンス)

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

(inheritance)

20

Page 21: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

21

位置

速度

燃料

進め

どこ?

変速

容量

補給

再利用可能ロボット

新操作

新データ

継承(インヘリタンス)親を再利用して子を作る

位置

速度

燃料

進め

どこ?

変速

使い捨てのロボット

親 子スーパークラス

サブクラス

オブジェクト指向の特徴は,すでに作ったコードを再利用して機能拡張をしていく仕組みが整っていることである.それが継承(インヘリタンス)という機能である.

この例では,これまで作成した(使い捨ての)ロボットを拡張して,再利用可能なロボットを作ろうとしている.つまり,燃料が切れたら,燃料補給できる機能を追加する.

新しいフィールドとして,燃料タンクの「容量」を追加する.

新しいメソッドとして,「補給」メソッドを追加する.

このようなクラス間の関係を,図のように,親/子と呼んだり,スーパークラス/サブクラ

スと呼んだりする.「ものつくり」の観点から言えば,スーパークラス(親クラス)は部品であり,ソフトウェア部品メーカーが供給することもある.それを目的に合わせてユーザ側のプログラマーがカスタマイズしたり機能拡張するなど,有効に再利用して作るものがサブクラス(子クラス)である.

Page 22: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

22

サブクラスの定義新属性,新機能,新コンストラクタのみ記述

class 再利用可能ロボット extends ロボット{int 容量;

void 補給() {燃料 = 容量;

}

再利用可能ロボット(int p, int v, int f, int c) {super(p, v, f);容量 = c;

}}

スーパークラスの指定新操作

新データ

新コンストラクタ

スーパークラスを書き直したり再コンパイルする必要はない

Javaではこの図のようにextends親クラス名

と書くことによって,親クラスを再利用して子クラスを定義できる.この例では,すでに作成した「ロボット」クラスを親クラスとし,その子クラスとして「再利用可能ロボット」クラスを定義している.

子クラスには,新しく追加するフィールドやメソッドだけを記述する.すでに親クラスで定義してあるフィールドやメソッドは,書かなくても,あたかも書いてあるかのように,子クラスに引き継がれる.

また,この子クラスをコンパイルする際には,スーパークラスを書き直したり,再コンパイルする必要はない.さらに重要なのは,スーパークラスのソースコード(ソースファイル)は無くてよく,そのコンパイルされたコード(クラスファイル)さえあればOKである.これは特にスーパークラスが商用で,価格のある商品の場合に重要である.スーパークラスを作成したソフトウェアメーカーは,それを販売するにあたって,ふつうはソースコードを公開したくない.公開すれば他社等に設計情報を知られるからである.Javaの場合,スーパークラスを購入したユーザーは,APIだけを知っていれば,ソースファイルがなくても,クラスファイルさえあれば,購入したスーパークラスを部品として利用し,子クラスを自分で定義できるのである.

Page 23: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

23

継承のクラス図

ロボット

int 位置int 速度int 燃料

int どこ?( )void 変速(int 速度)int 進め( )

再利用可能ロボット

int 容量

void 補給( )

スーパークラス

クラス図を書くときには,子クラスから親クラスに矢印を付けておく.

Page 24: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

24

継承の使用例

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回押し直している.

Page 25: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

特徴3:ポリモーフィズム(多相性)

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

(polymorphism)

25

Page 26: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

26

ポリモーフィズム(多相性)同じメッセージでもクラスによって処理が異なる

メッセージ

.進め( )進め

ロボットクラス

進め

船クラス

.進め( )

.進め( )

授業を進める

先生クラス

進め

このスライドに図示してある3つのクラス(ロボット,船,先生)に,いずれも「進め」メソッドがあるとしよう.3つのメソッドの内容(プログラムコード)は全く異なるものである.ロボットが「進む」とは,足を動かすプログラムコードを実行することだし,船が「進む」とは,スクリューを回転させるコードを実行することである.先生が「進む」とは,脱線していた授業を進ませることである.したがって,本来なら異なるメソッド名を付けるのがスジである.

しかし,人間にとって「進め」という言葉が適切なら,その言葉を共通に使えるようにした方が便利である.言葉の数の節約になり,人間にとって心理的に覚えやすい.

プログラミングの世界でその考え方を採り入れたのが「ポリモーフィズム」という機能である.(このスライドでは「多相性」という和訳を採用したが,「多態性」,「多様性」などと呼ばれるときもある.カタカナ書きでも,「ポリモフィズム」,「ポリモルフィズム」などの表記が使われることがある.)

オブジェクト指向の言葉で述べると,「同じメッセージ(メソッド)でも,受け手のオブジェクトのクラスによって,処理(意味)が異なる」という機能である.ここで「メッセージ」とは,メソッド呼び出しの記述内容(メソッド名+引数の列)のことで,さきほどの説明の中で,私たちが操作するコントローラーからロボットに送信される情報のことをいう.また「同じメソッド」と言っているのは,一般には,メソッドの名前が同じであることに加えて,そのインタフェース(すなわち,引数の数と型,およびメソッドからの戻り値の型)までも同じであることを指している.

Page 27: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

27

型の階層(包含)

進め 進め進め

ロボット 型 船 型 先生 型

進めるもの 型

「ロボット」クラスのオブジェクトは「ロボット」型というデータ型である.同様に,「船」クラスは「船」型,「先生」クラスは「先生」型である.これらのクラス(データ型)は,共通に「進め」という同一の名前をもつメソッドをもっている.

そのような共通性を認識して,これらの複数のデータ型をまとめて,1つのデータ型として総称的に定義することができる.このスライドの例ではそれを「進めるもの」という名前のデータ型としている.

Page 28: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

28

「進めるもの」のインタフェース

interface 進めるもの {int 進め();

}

抽象メソッド

Javaでこの考え方を実現する方法の1つが,「インタフェース」という機能である.その書き方はクラスの書き方と似ているが,class のかわりに interface というキーワードを用いる点が異なる.最も重要な違いは,メソッドの本体({ と }で囲まれて記述されるプログラムコード)を書くことが許されない点である.そのようなメソッドを抽象メソッドという.

このJavaコードの例は,「進めるもの」は,int 進め();

というメソッドを共通に持っていることを宣言している.

Javaで良く使われるインタフェースとして,Runnable インタフェースというのがある.これは,runメソッドを持つクラスを総称するためのもので,実際にはつぎのように定義されている.

interface Runnable {void run( );

}

Page 29: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

29

「進めるもの」の実装class ロボット implements 進めるもの{int 位置;int 速度;int 燃料;

int どこ?() { return(位置); }

void 変速(int 新速度) { 速度 = 新速度; }

int 進め() {if (燃料 > 0) {

位置 = 位置 + 速度;燃料 = 燃料 - 1;return 0;

} else return (-1);

}

ここを追加する

ロボット型が,進めるもの型に含まれることを,implements というキーワードを用いてこのスライドのように記述する.

このような場合,「ロボット」クラスは「進めるもの」インタフェースを「実装している」という.Javaの約束によって,インタフェースを実装するクラスの中では,そのインタフェース内で記述された抽象メソッドの本体を具体的に記述する必要がある.この例の場合,「進めるもの」インタフェースには,int進め( ) という抽象メソッドが記述されていたことを思い出そう.したがって,「ロボット」クラスの中で,int進め( ) メソッドの本体が具体的に記述されている.

Page 30: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

30

実装のクラス図

ロボット

int 位置int 速度int 燃料

int どこ?( )void 変速(int 速度)int 進め( )

interface 進めるもの

int 進め( )

実装

ロボットが「進めるもの」を実装していることを,破線の矢印を使って,このようなクラス図で表す.

Page 31: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

31

ポリモーフィズムの使用例いろいろな「進めるもの」を統一的に進ませる

進めるもの[] A = new 進めるもの[3];

A[0] = new ロボット(0,1,10);

A[1] = new 船("横浜");

A[2] = new 先生("数学","舞黒素太");

0 1 2

進め 進め進め配列A

ポリモーフィズムが便利と感じるようなプログラムの例を紹介しておこう.それは同じインタフェースが実装されたいろいろなクラスのオブジェクトを一次元配列に記憶しておき,それらに対して同じメッセージを送る(同じ名前のメソッドを実行する)ことにより,各オブジェクト特有の適切な動作を統一的なコーディングによって起こさせる例である.

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つのデータ型を包含する「進めるもの」型の配列を導入することにより,すべてを記憶できるようになる.なぜなら,ロボットも船も先生も「進めるもの」型という同じデータ型に属するからである.

Page 32: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

32

ポリモーフィズムの使用例(続き)いろいろな「進めるもの」を統一的に進ませる

進めるもの A[] = new 進めるもの[3];

A[0] = new ロボット(0,1,10);

A[1] = new 船("横浜");

A[2] = new 先生("数学","舞黒素太");

for(i=0; i<3; i++) A[i].進め();

0 1 2

進め 進め進め配列A

さて,つぎに進もう.ここが山場である.前のコードに続いて,このスライドでは 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ループは基本的にほとんど書き直す必要はない.(反復回数の3を5にする程度か。)しかし,if 文を使うプログラムでは,if 文の条件判定を新クラス向けに追加しなければならないので,このfor文を書き直し,再コンパイルする必要が生ずるのである.

このようなプログラミングテクニックは Java のプログラムコードでたくさん見かけるものなので,ぜひ覚えておこう.良く知られているものは,Runnableインタフェースである.Javaでは,「アニメーションを動かすと同時に,GUIのクリックも受け付ける」などのように,複数のプログラムを同時に動かすときには,スレッド(Thread)と呼ばれるオブジェクトを使う.その場合,プログラマは,応用に合わせて,オブジェクトに void run( ) というメソッドを記述しておく必要がある.この run ( )メソッドはJavaが事前に用意している Runnableというインタフェースの中で記述された抽象メソッドである.プログラマは,Runnableインタフェースを実装するようなクラスを自分で定義し,その中でrun ( )メソッドの中身を具体的に記述できる.つまり,先ほどの説明と比較すると,「進め」メソッドが run ,「進めるもの」インタフェースが Runnable に対応している.

Page 33: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

33

オブジェクト指向のまとめ

基本用語– オブジェクト,フィールド,メソッド,メンバ– クラス,インスタンス– ゲッター,セッター,コンストラクタ– スーパークラス,サブクラス,クラス図– インタフェース,抽象メソッド,実装

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

このスライドでまとめた用語のおよそのイメージが,それぞれ数秒で想起されるように復習してね.

Page 34: オブジェクト指向プログラミングkussharo.complex.eng.hokudai.ac.jp/~kurihara/classes/SE/09-object.pdf · 1 オブジェクト指向プログラミング OBJECT-ORIENTED

演習問題 9

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

34