• 検索結果がありません。

Microsoft PowerPoint - 09-object

N/A
N/A
Protected

Academic year: 2021

シェア "Microsoft PowerPoint - 09-object"

Copied!
34
0
0

読み込み中.... (全文を見る)

全文

(1)

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

OBJECT-ORIENTED PROGRAMMING

9

ソフトウェア工学

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

(2)

2

構成

Part1

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

Part2

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

1 カプセル化

2 継承(インヘリタンス)

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

今回の授業では,オブジェクト指向プログラミングの最も特徴的な考え方を学ぶ. 具体的なプログラミングはJavaを用いるが,Javaの詳細を学ぶことが目的ではない. Part1でオブジェクト指向の基本概念を説明した後,Part2でオブジェクト指向の3大特 徴を学ぶ.

(3)

Part1

(4)

4

X 軸方向

のみに進む

ロボット

オブジェクトとは?

データと操作をカプセル化した「もの」

位 置 速 度 燃 料

データ

フィールド

進 め どこ? 変 速

オブジェクト

カプセル化

メンバ

操作

メソッド

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

(5)

5

+1

10

進 め どこ? 変速

メモリ内に

オブジェクトがうようよできる

位置

速度

燃料

8

-1

8

進 め どこ? 変 速

-4

2

0

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

(6)

6

船 クラス

ロボット クラス

いろんな種類(クラス)の

オブジェクトが共存する

8

1

6

7

2

4

2

3

1

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

(7)

オブジェクトはクラス

(ひな形)

から

生成されるインスタンス

(実例)

位 置 速 度 燃料 どこ? 変速 進 め 2 3 4

インスタンス

クラス

2 9 2 5 4

操作(メソッド)は

クラスで共通

データ(フィールド)は

インスタンス毎

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

(8)

8

Javaではクラスを記述する

ロボットになったつもりで書く)

class ロボット

int

位置

;

int

速度

;

int

燃料

;

int

どこ?

() {

return(位置);

}

void

変速

(int 新速度) {

速度 = 新速度;

}

続 く

クラス名

フィールド名

種々の名前には

日本語を使える

メソッド名

整数型

値を戻す

戻り値の

データ型

戻り値

なし

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

(9)

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

class ロボット {

int 位置;

int 速度;

int 燃料;

//---int

進め

() {

if (燃料 > 0) {

位置 = 位置 + 速度;

燃料 = 燃料 - 1;

return 0;

} else {

return (-1);

}

}

再掲

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

(10)

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の頭文 字.)

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

(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 ループの中で,rococo.どこ?( ) によって現在位置を 取得し,それが10未満である間,ループの中で進めボタンを連打する.現在位置が10 以上になった時点でプログラムは停止する.このようにして,ロボットクラスで定義された 3つのメソッド「進め」,「変速」,「どこ?」を(コントローラーのボタンを押しているかのよう に)適切に呼び出しながらロボットを動かすプログラムである. プログラミングの際には,ロボットを作る「メーカー」と,ロボットを買って動かす「ユーザ -」との区別が大事である.メーカーは,ロボットを動かす汎用的なソフトウェア部品をク ラスとして制作する.そのプログラムは自分がロボットになったつもりで書く.それに対し てユーザーは,自分の応用目的に応じて,アプリケーションを制作する.そのプログラム は自分がロボットのコントローラーを持ったつもりで書く.

(12)

Part2

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

1 カプセル化

2 継承(インヘリタンス)

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

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

(13)

特徴1:カプセル化

カプセル化

2 継承(インヘリタンス)

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

(14)

14 船のフィールドの宣言 船のメソッドの宣言

船 クラス

制作者B

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

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

ロボット クラス

使

アクセス不可

カプセル化

制作者A

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

(15)

カプセル化

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

フィールド

メソッド

メソッド

メソッド

メソッド

フィールド

フィールド

アクセス

オブジェクトとは

,

データと操作をカプセル

化した「もの」

.

メソッド名

(引数, ... , 引数)

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

(16)

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 コンストラクタ (引数, … ,引数) という形式を用いる.

(17)

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

ge

tP

os

iti

on

( )

Robot( p )

se

tP

os

iti

on

( p

)

メソッド

Position

アクセス

.setPosition(10)

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

(18)

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)と呼ばれることがある.

(19)

ロボットのクラス図

ロボット

int 位置

int 速度

int 燃料

ロボット(int p, int v, int f )

int どこ?( )

void 変速(int 新速度)

int 進め( )

コンストラクタ

ゲッター

セッター

オペレータ

(一般のメソッド)

これはこれまで作ってきた「ロボット」クラスのクラス図である. 「どこ?」メソッドはゲッター,「変速」メソッドは セッターになっている. 「進め」メソッドはゲッター, セッターのような基本的なメソッドではなく,このロボット特有 の応用的なメソッドである.

(20)

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

1 カプセル化

継承(インヘリタンス)

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

(inheritance)

20

(21)

位置 速度 燃料 進め どこ? 変速 容量 補給

再利用可能

ロボット

継承(インヘリタンス)

親を

再利用

して子を作る

位置 速度 燃料 進め どこ? 変速

使い捨ての

ロボット

親 子

スーパークラス

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

(22)

22

サブクラスの定義

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

class 再利用可能ロボット

extends ロボット

int 容量;

void 補給() {

燃料 = 容量;

}

再利用可能ロボット(int p, int v, int f,

int c) {

super(p, v, f);

容量 = c;

}

}

スーパークラス

の指定

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

(23)

継承のクラス図

ロボット

int 位置

int 速度

int 燃料

int どこ?( )

void 変速(int 速度)

int 進め( )

再利用可能ロボット

int 容量

void 補給( )

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

(24)

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

(25)

特徴3:ポリモーフィズム

(多相性)

1 カプセル化

2 継承(インヘリタンス)

ポリモーフィズム

(多相性)

(26)

26

ポリモーフィズム

多相性

同じメッセージでもクラスによって処理が異なる

メッセージ

.

進め( )

進め

ロボットクラス

進め

船クラス

.

進め

( )

.

進め

( )

授業を

進める

先生クラス

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

(27)

型の階層(包含)

進め

進め 進め

ロボット

先生

進めるもの

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

(28)

28

進めるもの

」のインタフェース

interface 進めるもの {

int

進め

();

}

抽象メソッド

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

(29)

進めるもの

」の実装

class ロボット

implements 進めるもの

int

位置

; int

速度

; int

燃料

;

int

どこ?

() { return(位置); }

void

変速

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

int 進め() {

if (燃料 > 0) {

位置 = 位置 + 速度;

燃料 = 燃料 - 1;

return 0;

} else {

return (-1);

}

}

ここを追加する

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

(30)

30

実装のクラス図

ロボット

int 位置

int 速度

int 燃料

int どこ?( )

void 変速(int 速度)

int 進め( )

interface

進めるもの

int 進め( )

実装

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

(31)

ポリモーフィズムの使用例

いろいろな「進めるもの」を統一的に進ませる

進めるもの

[] A = new

進めるもの

[3];

A[0] = new

ロボット

(0,1,10);

A[1] = new

("横浜");

A[2] = new

先生

("数学","舞黒素太");

0

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

(32)

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

進め

進め

進め

さて,つぎに進もう.ここが山場である.前のコードに続いて,このスライドでは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 に対応している.

(33)

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

基本用語

– オブジェクト,フィールド,メソッド,メンバ

– クラス,インスタンス

– ゲッター,セッター,コンストラクタ

– スーパークラス,サブクラス,クラス図

– インタフェース,抽象メソッド,実装

特徴

– 1 カプセル化

– 2 継承(インヘリタンス)

– 3 ポリモーフィズム(多相性)

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

(34)

演習問題 9

オブジェクト指向プログラミングのもつ3つの

大きな特徴について説明しなさい.字数は全体

で400字程度とする.

参照

関連したドキュメント

Figure 6: To the left, the upper P-positions of Maharaja Nim in columns 8 to 12 have been computed, beginning with position (8, 13), and a perfect sector has been detected.. The

What relates to Offline Turing Machines in the same way that functional programming languages relate to Turing Machines?.. Int Construction.. Understand the transition from

The surfaces of degree 3 contained in X are either reducible in the union of three planes and hence linearly equivalent to 3R (when reduced they are the union of three planes meeting

1-1 睡眠習慣データの基礎集計 ……… p.4-p.9 1-2 学習習慣データの基礎集計 ……… p.10-p.12 1-3 デジタル機器の活用習慣データの基礎集計………

[3] Chari, Vyjayanthi, On the fermionic formula and the Kirillov-Reshetikhin conjecture, Int. and Yamada, Y., Remarks on fermionic formula, Contemp. and Tsuboi, Z., Paths, crystals

The construction of homogeneous statistical solutions in [VF1], [VF2] is based on Galerkin approximations of measures that are supported by divergence free periodic vector fields

Tsouli, Infinitely many solutions for nonlocal elliptic p-Kirchhoff type equation under Neumann boundary condition, Int. Journal

The proposed fifth-order nonlinear mathematical model represents the main characteristics of this nonlinear dynamic system, as servo valve dead zone, air flow-pressure