Microsoft PowerPoint - object.ppt [互換モード]

Similar documents
Microsoft PowerPoint - HITobject.ppt

Microsoft PowerPoint - 09-object

Microsoft PowerPoint - object.ppt

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

プログラミング基礎I(再)

プログラミング実習I

Microsoft PowerPoint - prog03.ppt

メディプロ1 Javaプログラミング補足資料.ppt

Javaの作成の前に

Microsoft PowerPoint - chap10_OOP.ppt

PowerPoint プレゼンテーション

JavaプログラミングⅠ

レコードとオブジェクト

GEC-Java

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

た場合クラスを用いて 以下のように書くことが出来る ( 教科書 p.270) プログラム例 2( ソースファイル名 :Chap08/AccountTester.java) // 銀行口座クラスとそれをテストするクラス第 1 版 // 銀行口座クラス class Account String name

PowerPoint プレゼンテーション

メソッドのまとめ

Javaプログラムの実行手順

プログラミング入門1

Prog2_12th

Microsoft PowerPoint - 09.pptx

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

プログラミング入門1

Prog2_9th

C#の基本

11 ソフトウェア工学 Software Engineering デザインパターン DESIGN PATTERNS デザインパターンとは? デザインパターン 過去のソフトウェア設計者が生み出したオブジェクト指向設計に関して, ノウハウを蓄積し 名前をつけ 再利用しやすいようにカタログ化したもの 各デ

Prog1_6th

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

コンピュータ中級B ~Javaプログラミング~ 第3回 コンピュータと情報をやりとりするには?

02: 変数と標準入出力

PowerPoint プレゼンテーション

Microsoft PowerPoint - prog04.ppt

Microsoft Word - no11.docx

プログラミング入門1

memo

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

02: 変数と標準入出力

書式に示すように表示したい文字列をダブルクォーテーション (") の間に書けば良い ダブルクォーテーションで囲まれた文字列は 文字列リテラル と呼ばれる プログラム中では以下のように用いる プログラム例 1 printf(" 情報処理基礎 "); printf("c 言語の練習 "); printf

JavaプログラミングⅠ

Java言語 第1回

JavaプログラミングⅠ

JavaプログラミングⅠ

Microsoft PowerPoint pptx

Microsoft Word - VBA基礎(6).docx

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

kantan_C_1_iro3.indd

ガイダンス

メソッドのまとめ

V8.1新規機能紹介記事

ガイダンス

PowerPoint プレゼンテーション

PowerPoint プレゼンテーション

コンピュータ工学講義プリント (7 月 17 日 ) 今回の講義では フローチャートについて学ぶ フローチャートとはフローチャートは コンピュータプログラムの処理の流れを視覚的に表し 処理の全体像を把握しやすくするために書く図である 日本語では流れ図という 図 1 は ユーザーに 0 以上の整数 n

第2回講義

プログラミング入門1

memo

GEC-Java

Microsoft PowerPoint - prog07.ppt

ガイダンス

レコードとオブジェクト

6 関数 6-1 関数とは少し長いプログラムを作るようになると 同じ処理を何度も行う場面が出てくる そのたびに処 理を書いていたのでは明らかに無駄であるし プログラム全体の見通しも悪くなる そこで登場す るのが 関数 である 関数を使うことを 関数を呼び出す ともいう どのように使うのか 実際に見て

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

関数の動作 / printhw(); 7 printf(" n"); printhw(); printf("############ n"); 4 printhw(); 5 関数の作り方 ( 関数名 ) 戻り値 ( 後述 ) void である. 関数名 (

人工知能入門

デザインパターン第一章「生成《

.NETプログラマー早期育成ドリル ~VB編 付録 文法早見表~

始めに, 最下位共通先祖を求めるための関数 LcaDFS( int v ) の処理を記述する. この関数は値を返さない再帰的な void 関数で, 点 v を根とする木 T の部分木を深さ優先探索する. 整数の引数 v は, 木 T の点を示す点番号で, 配列 NodeSpace[ ] へのカーソル

JAVA入門

Microsoft PowerPoint - 計算機言語 第7回.ppt

Microsoft PowerPoint ppt

Javaセキュアコーディングセミナー2013東京第1回 演習の解説

Sort-of-List-Map(A)

できるプログラマーを本気で育てる Java 超 Webプログラマーへの第 歩 第 2 回オブジェクト指向 テクノロジックアート 瀬 嘉秀

基本情報STEP UP演習Java対策

PowerPoint プレゼンテーション

情報処理Ⅰ演習

プログラミング入門1

ガイダンス

Prog1_15th

Microsoft PowerPoint ppt

Microsoft PowerPoint - lec06 [互換モード]

アスペクトの相互作用を解消するアスペクトの提案

プログラミング基礎

Microsoft PowerPoint - OOP.pptx

PowerPoint プレゼンテーション

Microsoft PowerPoint - handout07.ppt [互換モード]

PowerPoint Presentation

C#の基本2 ~プログラムの制御構造~

(2) 構造体変数の宣言 文法は次のとおり. struct 構造体タグ名構造体変数名 ; (1) と (2) は同時に行える. struct 構造体タグ名 { データ型変数 1; データ型変数 2;... 構造体変数名 ; 例 : struct STUDENT{ stdata; int id; do

Prog1_10th

レコード class Point attr_accessor("x", "y") インスタンス変数の宣言 point.rb

教材ドットコムオリジナル教材 0から始めるiアプリ (4) 0 から始める i アプリ (4) i アプリをプログラミングする際に必要なのは Java というプログラミング言語の基礎知識です 独自の命令や駆使してプログラミングをするわけですが Java というベースになっている言語を知らないでプログ

Microsoft Word 基_シラバス.doc

目次 はじめに 4 概要 4 背景 4 対象 5 スケジュール 5 目標点 6 使用機材 6 第 1 章 C# 言語 7 C# 言語の歴史 7 基本構文 8 C 言語との違い 9 Java 言語との違い 10.Netフレームワーク 10 開発資料 10 第 2 章 Mono 11 Monoの歴史 1

情報技術 Java の特徴 Java は現在 事務処理計算用プログラミング言語として開発された COBOL に取って代わり C 言語や C++ と並んで 現在最も使われているプログラミング言語の一つである Java は Write Once, Run Anywhere( プログラムを一度作成したらど

Microsoft Word - CygwinでPython.docx

JavaプログラミングⅠ

Transcription:

認知システム論 の授業では, 人工知能 (AI) のさまざまなアルゴリズムを学ぶことになるが, 可能ならばそれを実際のプログラミング言語で実装してみることが大事である. しかし, この授業では, 時間の関係でそこまで扱うことができないので, 興味のある人が将来, 自立的に実装できるように, 最小限のプログラミングの知識を今回の授業で学ぶ. 具体的には,AIプログラミング言語の歴史の概略を学んだ後, オブジェクト指向プログラミングの考え方とその3 大特徴およびJava 言語によるプログラムの記述例を学ぶ.JavaはAIプログラミング言語というわけではないが, 過去のAIプログラミング言語の研究成果の影響を受けて設計されており, インターネットなどと連携した現代的なAIプログラムを記述するのに適している. 1

人工知能の歴史の中で, 初期のころ (1960 年代以降 ) は,AIプログラミングといえば, それ専用のプログラミング言語を使うものと相場が決まっていた. それは基本的には LISP というリスト処理言語だった. ゴミ集め (garbage collection) という革新的なメモリ管理機能は, 不要になった ゴミ のデータを再利用して 環境 を整備するのに効果的だ.LISPは関数型言語と呼ばれる種類の言語であり, プログラムは関数の集まりとして定義され, 関数は他のデータと同格の 第 1 級 のオブジェクトとして扱われるため, 関数の引数として関数を渡したり, 関数のコードの中で関数を動的に生成して, その関数を関数からの戻り値とすることもできる. 1980 年代になると論理型言語である Prolog もAIプログラミング言語の仲間に加わった. 論理学における 述語 と呼ばれるものが, 手続きや関数のような基本的なプログラム部品として使われる. 述語のパラメータ ( 仮引数 ) とアーギュメント ( 実引数 ) は, パターン照合によって比較され, 両者が一致するように適切な 代入 が実行される. また, 実行すべき処理に 非決定的 な選択肢が含まれており, 深さ優先探索 ( バックトラック ) によって適切な選択肢を自動的に探索する機能がある. その後, プログラミング言語の発展もあり,AIの研究テーマも多岐にわたってきたことから, 最近では, 通常の言語でも十分,AIプログラムを書けるようになってきた. たとえば Java の登場である.Javaの特徴は, オブジェクト指向による再利用性の高いプログラミングができること. インターネット時代を反映して, ネットワークプログラミングが容易にできること. グラフィカル ユーザ インタフェース (GUI) のプログラミング機能が充実していることなどである. しかし, 最大の特徴は Write-Once Run-Anywhere ( 一度書けば, どこででも走る ) というキャッチフレーズで表現される可搬性 ( ポータビリティ ), あるいは事実上すべてのOSで動作して, しかも同じ動作をすることが保証されるプラットフォーム非依存性と呼ばれる性質によって, 一度作ったプログラムの実行コードを再コンパイルなしに事実上, ネットワーク上のどこででもただちに実行できることである. 2

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

4

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

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

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

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

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

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

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

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

13

14

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

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

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

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

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

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

21

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

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

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

再利用可能ロボットを使ってみよう. この例では, 再利用可能ロボット robo2 を生成し, for ループを使って 進め ボタンを 100 回連打する. ただし, 途中で燃料切れになったときは, 進め メソッドは負のエラーコードを返すので, 燃料を補給して, ボタンを 1 回押し直している. 25

26

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

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

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

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

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

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

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

34