オブジェクト 指 向 操 作 対 象 の 理 解 と 言 語 の 効 率 性 プログラム 理 論 と 言 語 Part2-1-1 関 連 したデータの 塊 を1つの もの として 認 識 (1) クラス= もの と もの に 付 随 した 操 作 系 (2) クラスのことはクラス 内 部 で 処 理 ブラックボックス 化 し 外 部 仕 様 を 明 確 化 部 品 としての 再 利 用 安 全 性 (3) もの と 処 理 の 独 立 性 を 高 め 処 理 も 部 品 化 操 作 そのものでなく 操 作 の 型 情 報 のみで 処 理 を 記 述 コードの 抽 象 化 再 利 用 役 割 機 能 と もの を 分 離 し 独 立 性 を 高 める (4) 複 雑 さに 対 処 するために 階 層 として 体 系 化 修 正 追 加 利 用 ( 特 にライブラリ ユーティリティ) 人 の 対 象 理 解 言 語 的 表 現 と 合 致 する 特 に 個 別 事 例 に 依 存 しない 抽 象 表 現 言 語 の 効 率 性 JAVA はオブジェクト 指 向 言 語 か? その 気 になれば オブジェクト 指 向 でプログラムが 書 ける 一 般 に 長 くなるが 可 読 性 安 全 性 再 利 用 性 は 高 まる そうでないプログラムも 書 ける 体 系 的 でない ものも 多 い 簡 単 な 場 合 はそれでもすむが 複 雑 になると 修 正 拡 張 再 利 用 が 困 難 プログラムを 書 くという 観 点 からは オブジェクト 指 向 は 処 理 対 象 と 処 理 を 体 系 化 す るための 作 法 であり オブジェクト 指 向 言 語 は そのための 言 語 的 装 置 (*) (*) 本 講 義 において Java を 題 材 にする 理 由 : 1. オブジェクト 指 向 の 主 要 な 概 念 は 全 て Java で 説 明 できること 2. プログラム 言 語 において 重 要 な 型 概 念 を 十 分 に 講 述 できること 3. 様 々な 場 所 で 実 際 に 良 く 使 われている 言 語 であること 4. CS 実 験 等 をとおして C 言 語 の 理 解 が 進 みつつあることを 考 慮 し Cと 構 文 的 に 近 いオブジェクト 指 向 言 語 であること ポインタについて: Java: 実 際 は ポインタのお 化 け 状 態 ポインタを 駆 使 するプログラミングは 一 般 に 難 しい Java: 比 較 的 に 安 全 にかつ 容 易 に 実 現 本 講 義 : 上 記 の 事 情 をある 程 度 説 明 する 1 2 はじめにオブジェクトありき まず 処 理 において 如 何 なるオブジェクトが 必 要 かを 考 える 対 象 の 分 析 理 解 その 理 解 を 言 語 的 に 顕 在 化 させるプロセス もの の 定 義 書 としてのクラス もの に 付 随 したメソッド( 演 算 基 本 操 作 ) 群 メソッドを 持 つ もの として 体 系 的 に 扱 う その 後 に メソッドにより もの を 操 作 処 理 する 手 続 き オブジェクト 指 向 言 語 =オブジェクト 定 義 操 作 言 語 では もの とは 何 か? 哲 学 論 議 はここではしない 計 算 機 の 中 での 出 来 事 メモリ 上 の 構 造 物 として 表 現 翻 訳 される もの 配 列 :プログラミングにおいて 不 可 欠 な もの これも 立 派 なオブジェクト int[] a; a = new int[3]; データの 集 まり {a[0], a[1], a[2] を1つの 配 列 と して 纏 めて 扱 う new int[3] : 配 列 領 域 を 割 当 生 成 配 列 は 要 素 から 構 成 され 添 字 を 与 え 要 素 へアクセス 特 に a は 領 域 全 体 の 名 前 ( 参 照 ) 領 域 を 生 成 する 仕 掛 け 一 般 のオブジェクト: フィールド 名 を 持 つ 要 素 からなり 添 字 の 代 わりにフィールド 名 ( 変 数 )で 要 素 にアクセス 特 定 のデータ 領 域 を 占 有 し 領 域 全 体 はオブジェクト 参 照 変 数 で 参 照 領 域 生 成 は コンストラクタ で 行 う 3 4
3 角 形 は3つの 点 からなる: まず 点 を 定 義 定 義 は 対 応 するクラスの 記 述 で 与 えられる class Point { //フィールド 変 数 double x, y, weight; //コンストラクタ( 生 成 方 法 ) Point(double x, double y, double w) { this.x=x; this.y=y; weight=w; //インスタンスメソッド // 各 オブジェクトに 直 接 作 用 //オブジェクトと 一 体 化 した 表 記 void show() { System.out.println( "x="+x+", y="+y+ " with weight "+weight); フィールドアクセス: this からは フィールド 名 x 一 般 に a.x Point a が 参 照 している オブジェクトの x フィールド 識 別 子 が 特 定 する 位 置 の 実 体 に 対 し x のフィールド 値 をとりだす Note: オブジェクトはCの 構 造 体 参 照 変 数 は 構 造 体 型 のポインタ 変 数 に 対 応 する メソッド( 関 数 )と 一 体 化 して 使 う 点 がオブジェクト 指 向 を 表 し ているが 上 記 の 図 ではその 事 情 を 十 分 説 明 できていない(インスタンス の 図 ) 後 で 詳 しく 述 べる Cの 構 造 体 オブジェクトと 参 照 変 数 はCの 構 造 体 とそのポインタと 似 ている 似 て(メモリ 上 の 構 造 物 という 点 は 同 じ) 非 なるもの ( 使 い 方 その 作 法 安 全 性 に 対 する 配 慮 が 全 く 異 なる) struct student{ int stnum; char stname[16]; ; struct student *stpt; /* ポインタ */ stpt->stnum (*stpt).stnum class Student{ int stnum; String stname; Student st; // 参 照 変 数 st.stnum stpt, st が 参 照 する 実 体 の stnum フィールドをゲット stpt, *stpt を 区 別 参 照 変 数 は Student 実 体 と 考 えてよい 書 き 方 非 なる 点 としては そもそもオブジェクトがメモリの 特 定 の 領 域 を 占 有 しているか? の 問 題 もある Java: 占 有 状 態 (システムが 管 理 ) C: アドレス 計 算 が 可 能 型 チェックが 甘 い 等 により 上 書 きの 危 険 性 プログラマの 責 任 5 6 参 照 変 数 はポインタか? - Cとの 比 較 参 照 関 係 と 内 部 状 態 の 変 化 答 え: 広 義 の 意 味 のポインタか? Yes Cと 同 じポインタか? アドレス 計 算 を 禁 止 参 照 機 能 に 限 定 厳 密 表 現 :Point の 参 照 変 数 aが 参 照 する( 指 す)オブジェクト 略 した 表 現 :Point a ( 単 に 点 a) 仮 の 名 前 : 変 数 と 実 体 の 参 照 関 係 は 動 的 に 変 化 内 部 状 態 も! 計 算 過 程 : 新 規 オブジェクトを 生 成 しながら (1) 参 照 関 係 の 変 化 (2) オブジェクトの 内 部 状 態 の 更 新 上 記 はメソッド 実 行 時 識 別 子 の 詳 細 は 知 る 必 要 はない 知 ったとしてもその 事 実 をコードに 反 映 で きない 識 別 しアクセスできることが 論 理 レベルで 保 障 されていれば 十 分 以 下 実 体 を 特 定 できる 論 理 的 なものとして 識 別 子 を 考 える 7 8
メソッド 呼 出 とパラメータ つぎに 3 角 形 を 定 義 する 基 本 データ 型 の 引 数 : ( 評 価 ) 値 を 引 数 パラメータに 代 入 ( 値 呼 出 ) 参 照 型 変 数 : 仮 = 実 が 実 行 され, 仮 変 数 と 実 変 数 が 同 一 のオブジェクトを 参 照 する class Triangle { //スタティック 変 数 static final int nofpoints=3; //オブジェクトはフィールドで 規 定 Point[] points = new Point[nofPoints]; //インスタンスメソッド //オブジェクトに 作 用 する 関 数 void show() { for (short i=0;i<nofpoints;i++) points[i].show(); // 3 角 形 に 対 する show() を 点 に 対 する show() を 使 って 定 義 クラス 情 報 ( 型 ) で 識 別 static final int nofpoints=3; クラスに 固 有 (インスタンスに 依 存 しない) 変 数 で クラスのスタティックメンバーともいう final 指 定 変 数 は 上 書 き 不 可 ただし 下 記 の 注 意 が 必 要 となる: 1. 基 本 データ 型 : 文 字 通 り 定 数 2. オブジェクト: 参 照 先 オブジェクトは 変 わらない しかし その 内 部 状 態 は 変 更 される 可 能 性 定 数 にするにはカプセル 化 が 必 要 9 10 コンストラクタ(オブジェクトの 占 有 領 域 を 作 成 ) デフォルト 生 成 : Triangle t = new Triangle(); 引 数 なしの 特 別 な 手 続 き Point[] points = new Point[nofPoints]; に 従 い 実 体 を 生 成 し t にセット この 場 合 配 列 領 域 の 確 保 ( 割 当 ) 明 示 的 な 生 成 =デフォルト+α Triangle t = new Triangle(p0,p1,p2); 右 辺 実 体 (の oid) を t にセット Triangle( // 引 数 付 の 手 続 き Point p0, Point p1, Point p2) { points[0]=p0; points[1]=p1; points[2]=p2; クラスのインスタンス 化 : コンストラクタを 適 用 し 実 体 オブジェクトを 生 成 する 行 為 定 義 生 成 操 作 オブジェクトの 定 義 をクラス 記 述 で 与 え コンストラクタでオブジェクトを 生 成 し インスタンスメソッドでオブジェクトを 操 作 する class triangletest { public static void main(string args[]) { Triangle t = new Triangle( new Point(1,2,3), // 各 点 実 体 (の 識 別 子 ) new Point(4,5,6), new Point(7,8,9) ); // 右 辺 のオブジェクト (の 識 別 子 ) を // 左 辺 の 変 数 (に 代 入 )に 参 照 させる t.show(); // 3 角 形 t に show() を 適 用 // オブジェクトの 操 作 は 手 続 きで 記 述 // 手 続 き 的 なオブジェクト 定 義 操 作 言 語 論 理 型 のオブジェクト 指 向 言 語 (OOLP) 関 数 型 のオブジェクト 指 向 言 語 (Common LISP) この 他 オブジェクト 指 向 のデータベース オブジェクト 指 向 の COBOL! などもある 扱 うデータの 基 本 単 位 としてオブジェクトを 許 すと こうなる デフォルトコンストラクタ: 引 数 なしで Triangle() { クラス 定 義 におけるデフォルトコンスタラクタの 扱 い 明 示 的 コンストラクタを 使 用 しない 宣 言 せずに 使 える 明 示 的 コンスタラクタを 使 用 デフォルト Triangle() を 使 うときはそれも 明 示 する 11 12
様 々なメソッドの 定 義 と 組 合 せ: 手 続 きを 記 述 class クラス 名 { //インスタンスメソッド: もの に 対 する 基 本 操 作 または 複 合 操 作 出 力 型 (クラス 名 または 基 本 データ 型 ) // ( 基 本 操 作 を 組 合 せた 操 作 ) メソッド 名 (パラメータ 型 変 数 名, ) { メソッド 本 体 (そのクラスのオブジェクト に 対 し 行 う 処 理 or オブジェクトがそのメソッドで 振 る 舞 う 動 作 の 記 述 ) class Point { double x, y, weight; double length(point p) {// 2 点 の 距 離 return Math.sqrt(Math.pow(x-p.x,2)+Math.pow(y-p.y,2)); // sqrt: 平 方 根 pow: べき 乗 Math クラスで 定 義 class Triangle { static final int nofpoints = 3; // 大 域 変 数 ( 定 数 ) Point[] points = new Point[nofPoints]; // double sumoflength() {// 3つの 辺 長 の 総 和 double sumoflength = 0.0; for (int i=0;i<nofpoints;i++) // i++ は i=i+1 の 略 記 sumoflength += points[i].length(points[(i+1)%nofpoints]); return sumoflength; // 整 数 n, m に 対 し n % m は m を 法 とした 剰 余 public static void main(string args[]) { Triangle t = new Triangle( new Point(1,2,3), new Point(4,5,6), new Point(7,8,9) ); if (t.checktriangle()) System.out.println(" 辺 の 長 さの 総 和 = "+ t.sumoflength()); else { System.out.println("3 角 形 ではありません 要 データチェック"); t.show(); ; 用 語 の 整 理 1: インスタンスとオブジェクト オブジェクト: 操 作 の 対 象 で 占 有 領 域 (インスタンス) と それを 処 理 するメソッドを 持 つ Cでも 構 造 体 のインスタンス 化 は 行 う しかし そのインスタンスは 関 数 (メ ソッド)と 言 語 的 に 一 体 化 しているわけではない プログラマが 必 要 に 応 じて そのインスタンスへのポインタを 関 数 に 渡 して 適 用 操 作 するだけ の 話 一 方 Java では 最 初 からインスタンスはメソッドと 一 体 化 されて 扱 われるこ とが 大 前 提 であり そのことがクラス 定 義 で 明 示 される それは 体 系 的 に 操 作 対 象 を 扱 うための 流 儀 であると 理 解 すること 13 14 操 作 により もの をクラス 分 けする オブジェクトがどのようなメソッドを 使 用 できるかはクラス 定 義 で 決 まる 逆 に 言 えば 各 オブジェクト 毎 にメソッ ドを 定 義 し 保 持 するのは 不 経 済 オブジェクト 毎 に 異 なるメソッドが 必 要 な 場 合 : 別 クラスの もの メソッドがクラスを 特 徴 づける カプセル 化 クラスの 利 用 クラス 間 相 互 作 用 は 一 般 に 複 雑 化 外 部 仕 様 : クラスとは? のメソッドを 持 つ もの ~ メソッド 中 心 の 設 計 仕 様 と 実 装 の 分 離 独 立 化 仕 様 に 関 わるメソッドのみ 公 開 内 部 的 な 実 装 は private に 外 部 からは 公 開 メソッドのみで 操 作 隠 蔽 し 独 立 に 管 理 上 図 における 人 は 識 別 子 と 考 えてもよい 以 後 概 念 図 において 人 記 号 は 識 別 子 もしくはインスタンス とする オブジェクト 指 向 はさらなる 構 造 化 を 促 す: 独 立 したクラスの 列 挙 から 構 造 化 されたクラス 群 1. クラス 階 層 インタフェース 階 層 2. 内 部 クラス( 一 般 には クラスの nesting) 15 16
アクセス 制 御 の 原 則 フィールドは 原 則 private に ( 不 用 意 なアクセスによる 状 態 参 照 更 新 を 抑 制 する) ゲッター getattr() +セッター setattr() パッケージと public の 例 メソッドに 対 するアクセス 制 御 同 一 パッケージ( 同 一 ディレクトリ)を 想 定 した 場 合 : 無 修 飾 のメソッド: パッケージ 内 で 公 開 private メソッド: クラス 内 のみで 有 効 一 般 には パッケージの 作 り 方 に 依 存 ( 特 に public) 複 数 のパッケージ( 複 数 のディレクトリ)の 場 合 : public: 全 てに 公 開 protected, final: クラス 階 層 導 入 時 むやみに 意 味 もなく public をつけない! パッケージ 配 布 公 開 の 際 の 外 部 仕 様 ソースコード 解 読 時 の 構 文 上 の 情 報 インタフェースの 定 数 とメソッドは must be public protected: パッケージ 内 + 下 位 クラスに 公 開 final 定 数 メソッド: 上 書 きを 許 さない クラスに 対 しても public, private, final 無 修 飾 等 の 修 飾 が 可 能. 例 えば public にしないと 他 パッケージから 利 用 できない final にすると 継 承 拡 大 を 許 可 しない 17 18 Integer クラス in パッケージ java.lang http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/integer.html java.lang クラス Integer java.lang.object java.lang.number 階 層 java.lang.integer すべての 実 装 されたインタフェース(のメソッドを 実 装 ): Serializable, Comparable<Integer> ---------------------------------------------------------- フィールドの 概 要 static int MAX_VALUE int に 設 定 可 能 な 最 大 値 (231-1) を 保 持 する 定 数 です static int MIN_VALUE int に 設 定 可 能 な 最 小 値 (-231) を 保 持 する 定 数 です static int SIZE 2 の 補 数 バイナリ 形 式 で int 値 を 表 すのに 使 用 されるビット 数 です static Class<Integer> TYPE int のプリミティブ 型 を 表 す Class インスタンスです コンストラクタの 概 要 Integer(int value) 指 定 された int 値 を 表 す 新 しく 割 り 当 てられた Integer オブジェクトを 構 築 します Integer(String s) String パラメータで 示 される int 値 を 表 す 新 しく 割 り 当 てられた Integer オブジェクトを 構 築 しま メソッドの 概 要 static int bitcount(int i) 指 定 された int 値 の 2 の 補 数 バイナリ 表 現 での 1 のビットの 数 を 返 します byte bytevalue() この Integer の 値 を byte として 返 します int compareto(integer anotherinteger) 2 つの Integer オブジェクトを 数 値 的 に 比 較 します static Integer decode(string nm) String を Integer にデコードします double doublevalue() この Integer の 値 を double として 返 します boolean equals(object obj) このオブジェクトを 指 定 されたオブジェクトと 比 較 します. ラップクラス 注 意 ラップクラス: 基 本 データ 型 のデータ をオブジェクト 化 したもの オブジェクト: 参 照 変 数 で 指 される もの 基 本 データ 型 のデータ: データそのも の 32 bit 整 数 なら,31 ビットの2 進 表 現 と 1 ビット の 符 号 部 右 図 の 場 合,a.intValue() で,x フィールドの 値 ( 整 数 )がとれる. 言 語 によっては,ラップクラスと 基 本 データ 型 を 区 別 せずに 扱 えるもの もある 19 20
整 数 リスト: 再 帰 的 データ 構 造 の 例 リスト( 要 素 の 並 び)x1,x2, xn 要 素 は 次 の 要 素 へのポインタを 持 つ リスト: 先 頭 要 素 へのポインタ 空 リスト: null( 要 素 は 指 さない) class IntCell {// 要 素 の 再 帰 的 クラス private int value ; int getvalue() {return value; private IntCell next; IntCell next() {return next; IntCell(int value) {this.value = value; IntCell(int value, IntCell cell) { this.value = value; next = cell; void showvalue() {System.out.print(value+" "); class IntList { private int size = 0; private IntCell firstcell = null; void tail() { firstcell = firstcell.next(); size--; void cons(int x) { if (size == 0) firstcell = new IntCell(x); else { IntCell nextfirstcell = new IntCell(x,firstCell); firstcell = nextfirstcell; ; size++; 用 語 の 整 理 2: obj.m(p1,.., pn) の 読 み 方 オブジェクト obj に 対 し メソッド m(p1,.., pn) を 適 用 obj に 対 し m(p1,.., pn) を 実 行 オブジェクト obj に 対 し メソッド m(p1,..,pn) を 呼 び 出 す メソッドはオブジェクトの 所 有 物 本 講 義 では 特 に 区 別 しない この 他 オブジェクトをエージェント( 処 理 主 体 )と 考 え オブジェクトにメッセージを 送 る オブジェクトはメッセージに 対 応 するメソッドを 持 つか らそれを 実 行 void show() { IntCell presentcell = firstcell; for (int i=0;i<size;i++) { presentcell.showvalue(); presentcell = presentcell.next(); ; System.out.println("#end_of_list"); 21 22 メッセージパッシング オブジェクト obj (レシーバ)に メッセージ m をパラメータ p1,.., pn で 送 る 送 られた 方 は m を 処 理 するメソッドを 持 つ メッセージ ~ メソッド class Teacher { void assignrept(student st, Task task) { Answer ans = st.report(task); // st に report せよ との // メッセージを 発 信 し // 結 果 を ans で 受 ける if (ok(ans)) { else {; class Student { //メッセージを 受 けたときの // 動 作 ~ メソッドそのもの Answer report(task task) { Answer myanswer = new Answer(); return myanswer; // 解 答 を myanswer で 返 す 実 際 の 例 題 は FAのシミュレーション (statisfa.java, fa.java) で 示 す 受 理 機 械 : メッセージパッシング 例 各 状 態 をオブジェクトに. 状 態 は 受 理 / 非 受 理 の 情 報 を 持 つ 入 力 記 号 列 str を 受 け 取 り 次 の 状 態 next に 処 理 依 頼 のメッセージを 投 げ( 送 り) next は 自 分 のメソッド process で 処 理 を 続 ける class State { private static final short nofsymbols = 2; // 入 力 記 号 は {0,1 private String name; private boolean accept; // 受 理 状 態 情 報 private State(String n, boolean f) {name = n; accept = f; private State[] nextstates = new State[nofSymbols]; void definenextstate(state next0, State next1) { nextstates[0] = next0; nextstates[1] = next1; private short head(string str) {return Short.parseShort(str.substring(0,1)); private String tail(string str) {return str.substring(1,str.length()); private void process(string input) { if (input.length()!=0) nextstates[head(input)].process(tail(input)); else if (accept) System.out.println("OK"); else System.out.println("NG"); public static void main(string args[]) { State q0 = new State("q0", false), q1 = new State("q1", false), q2 = new State("q2", true), q3 = new State("q3", false) ; q0.definenextstate(q1, q3); q1.definenextstate(q3, q2); q2.definenextstate(q1, q3); q3.definenextstate(q3, q3); q0.process(args[0]); この 例 題 では 単 一 クラスなので,main(String[]) を 除 き, 全 てのフィール ドとメソッドを private にしても 正 しく 動 作 する. 全 く 同 じ 理 由 で,この 場 合 は private を 付 けなくても 構 わない 23 24
Definition of A: A consists of B 1, B 2, オブジェクト 指 向 : 言 語 的 な 定 義 のスタイルに 対 応 Aの 定 義 書 : クラスAのオブジェクトは クラス(or 基 本 型 )B j のフィールドからなり のメソッドを 使 って 操 作 します ( 構 成 要 素 (part of, has_a 関 係 ) クラスのメンバー A isa B, ora is defined as a B such that A extends B AはBを 継 承 し 拡 大 Aに 固 有 なフィールドやメソッドを 追 加 A has a role/function of B B: インタフェース A implements B 機 能 を 持 つ ~ 役 割 機 能 を 実 現 する 手 段 メソッドを 具 体 的 に 持 つ( 実 装 ) 多 態 性 (ポリモルフィズム) 様 々な 役 割 や 機 能 を 実 装 クラスで 記 述 (クラスと 機 能 の 分 離 独 立 化 を 促 進 ) 25 クラス 定 義 のまとめ class Point { private double x,y; Point(double x, double y) { this.x = x; this.y =y; void show() { System.out.println(" x="+x +", y="+y); class Triangle { private static final int nofpoints=3; private Point[] points = new Point[nofPoints]; private Triangle(Point p0, Point p1, Point p2) { points[0]=p0; points[1]=p1; points[2]=p2; private void show() { for (short i=0;i<nofpoints;i++) points[i].show(); public static void main(string args[]) { Triangle t = new Triangle( new Point(1,2), new Point(4,5), new Point(7,8) ); t.show(); //void main(string[]) は //ここでは Triangle に 組 み 込 んだ 実 行 時 : クラスは 生 成 されたオブジェクトの 集 まり + 大 域 変 数 (static variable)の 値 を 管 理 コンパイル 時 : オブジェクトの 定 義 書 として 記 述 の 集 まり 記 述 は クラスのメンバー( 構 成 要 素 )と 呼 ばれる 変 数 やメソッドの 各 々に 対 し 行 われる フィールド 変 数 : オブジェクトの 属 性 基 本 データ 型 もしくはオブジェクト 参 照 変 数 フィールド 記 述 がコンスラクタの デフォルト 動 作 を 決 める インスタンスメソッド: オブジェクトに 直 接 作 用 する 手 続 き オブジェクト: this で 表 記 ( 必 要 ならば) スタティック (static) メンバー スタティック 変 数 :クラスが 保 持 し 各 オブジェクトに 依 存 しない 変 数 スタティックメソッド: オブジェクトに 依 存 しない 手 続 き public static void main(string args[]) java クラス 名 引 数 そのクラスの main が 実 行 される クラス 毎 につけてよい 型 は void main(string[]) 引 数 型 を 別 に すると オーバーロード 左 記 では main は Triangle のメンバー 別 クラスで main を 動 作 させる 場 合 Triangle() と void show() の private 指 定 は 外 す(メソッドにアクセスできないから) 26 スタティックメンバーについて オブジェクト 指 向 では 先 んずオブジェクトとクラス 設 計 その 次 に 手 続 き 等 の 設 計 個 々のオブジェクトに 依 存 しない 定 数 変 数 メソッドがあ れば スタティックメンバーにする 具 体 にスタティックメンバーが 必 要 となる 場 面 例 : コンストラクタに 準 じた 作 用 を 持 つメソッド クラス 固 有 の 定 数 やオブジェクト(static final) 個 々の もの に 依 存 しないクラス 固 有 の 処 理 手 続 き 基 本 データ 型 に 関 する 型 変 換 や 数 値 関 数 など ラップクラス や Math で 提 供 される int Integer.parseInt(String), double Math.sqrt(double) 再 帰 呼 び 出 しに 関 する 補 足 C 同 様 Java でも 再 帰 は(static, instance methods ともに) 使 える 関 数 型 でやったようなスタイルでのメソッド 定 義 もOK 処 理 系 からみると 再 帰 と 非 再 帰 の 区 別 は 全 くない! 一 般 形 f の 定 義 本 体 中 で 別 のメソッド g を 呼 び 出 す 再 帰 特 に g = f なだけで 何 ら 処 理 は 変 わらない ただし 計 算 量 に 注 意 すること // フィボナッチの 数 列 f(n)=f(n-1)+f(n-2), f(1)=f(0)=1 class Fibonacci{ static int rec_fib(int n) {//この 場 合 指 数 爆 発 if (n==0 n==1) return 1; return rec_fib(n-1)+rec_fib(n-2); static int it_fib(int n) {// 繰 り 返 し // 定 数 領 域 線 形 時 間 if (n==0 n==1) return 1; int nminus1 = 1, nminus2 = 1, tmp; for (int i=1;i<n;i++) { tmp = nminus1; nminus1 = nminus1 + nminus2; nminus2 = tmp; ; return nminus1; 27 28
スパゲッティプログラム:よくあるパターンその1 static void main(string args[]) で 全 てを 書 こうとし 補 足 的 に static メソッドを 用 いる スパゲッティプログラムへの 道 処 理 対 象 と 手 続 きの 両 方 が 構 造 化 されていないため バグとり 修 正 再 利 用 機 能 の 追 加 が 困 難 書 き 直 した 方 が 早 い 修 正 箇 所 機 能 追 加 デバッグ 箇 所 を 特 定 しずらく ズルズルと 全 体 がついてくる スパゲッティ ( 結 局 多 くの 箇 所 を 食 べないとダメ もしくは 切 るのが 大 変 ) スパゲッティプログラム:よくあるパターンその2 Cで 書 いていたとき 構 造 体 とポインタに 苦 手 意 識 があり その 惰 性 でつい 配 列 だけで 書 いてしまう 関 連 する 配 列 や 変 数 がばらばらで 関 連 性 を 見 出 すためには スパゲッティ 状 態 コメントをつけて 対 処 する 人 も 多 い コメントはダラダラとつければ 良 いというものでない OOPL 構 造 体 と 参 照 は 簡 単 にかつより 安 全 にカプセル 化 できる: クラスを 定 義 し メソッドで 実 体 を 処 理 する 29 30 スパゲッティプログラム3: 例 static int nofitems = 0; // 商 品 数 static int[] stock = new int[10000], price = new int[10000]; static String[] itemname = new String[10000]; static void additem(int initialstock, int price, String itemname) { if (nofitems == 10000) { System.out.println("sorry, full list"); return; ; stock[nofitems] = initialstock; price[nofitems] = price; itemname[nofitem++] = itemname; まず 重 要 な 定 数 10000 のスパゲティ 後 で 商 品 コードも 必 要 になった 追 加 : static int[] code = int[10000]; 関 連 するメソッドの 引 数 や 本 体 部 の 修 正 static void additem( int initialstock, int price, String itemname, int codenumber) { code[nofitems] = codenumber; さらに 商 品 コードで 商 品 リストをソート code の 値 による 並 び 替 えで 同 時 に stock, price, itemname 配 列 も 操 作 修 正 箇 所 が 増 え しかもその 場 所 が 集 中 して いるとは 限 らない OOPLでは class Item { private int stock, price; Item(int initialstock, int price) { stock=initialstock; this.price=price; その 他 のメソッド class ItemList { private static int MaxNof = 10000; private int nof = 0; private Item[] list = new Item[MaxNof]; void add(item item) { if (nof!= MaxNof) list[nof++] = item; else System.out.println("full list"); code や name の 追 加 は 対 応 する フィールドとコンストラク タの 修 正 のみ add(item) は 修 正 の 必 要 なし 一 般 に 参 照 変 数 で 実 体 を 丸 ごと 渡 すので 関 数 メソッドの 引 数 は 少 なくなる また 例 えば ソートのときも item.code の 大 小 関 係 で 実 体 そのものを 並 び 替 えれば それでOK 例 えば 実 体 の 交 換 : Item tmp = itemlist[i]; itemlist[i] = itemlist[j]; itemlist[j] = tmp; 喩 え 話 : 中 に 色 々なものが 入 っている 箱 を 他 に 移 動 するとき ある 順 序 で 並 び 替 えるときに 箱 の 中 身 をバラバラにして 移 動 あるいは 並 べ 替 えますか? この 場 合 の 箱 ~ オブジェクト 箱 の 中 身 ~ フィールド クラスによるカプセル 化 使 い 方 は 商 品 名 フィールドが 追 加 されたとして 例 えば ItemList itemlist = new ItemList(); itemlist.add(new Item(100,1200," 製 図 用 シャープペン")); 集 合 やリストは java.util に 色 々 定 義 されている 自 分 で 適 宜 定 義 し ても 良 い インタフェースで 話 す キャスト を 使 う class MyList { private static int MaxNof = 10000; private int nof = 0; private Object[] list = new Object[MaxNof]; void add(object obj) { if (nof!= MaxNof) list[nof++] = obj; else System.out.println("sorry, full list"); 31 32
オブジェクト 指 向 のストーリー 最 初 から 必 要 なオブジェクトとクラスを 切 り 出 す 作 業 他 のクラスとの 切 り 分 け 分 節 化 部 品 化 先 んず 対 象 のモデリング 設 計 その 次 にアルゴリズムの 設 計 と 解 析 その 次 の 次 にプログラミング 技 法 優 れたモデル 優 れたパッケージ(クラスの 集 合 ) 保 守 拡 張 利 用 が 楽 本 日 の 演 習 問 題 1 整 数 を 要 素 とする 線 形 リスト( 要 素 の 並 びを 表 し 参 照 構 造 が 一 方 向 のもの)について 述 べた 一 方 CS 実 験 で 双 方 向 リストをCのポインタで 実 現 する 課 題 を 行 ったと 思 う 課 題 の 手 引 書 と 本 講 義 の 線 形 リスト Java プログ ラムを 参 考 にし 実 験 課 題 に 対 する Java のクラスを 定 めよ 33 34 0.1 演 習 問 題 2-2 本 日 の 演 習 問 題 3: 有 限 オートマトン 下 記 の2つのメソッドを 当 該 クラスに 追 加 し なさい ただし ( 平 面 上 の) 点 とベクトルを 区 別 するために ベクトルのクラス MyVector を 定 義 し それを 利 用 した 上 で 下 記 のメ ソッドを 当 該 クラスに 追 加 すること 右 図 は 受 理 機 械 としての 有 限 オートマトンF Aの 例 である ただし q0 を 初 期 状 態 q2 を 受 理 状 態 とする 受 理 する 言 語 は {(01) n n 1 1. Point クラスのメソッド: boolean checkpointonline(point p1, Point p2); パラメータで 与 えた2 点 と 自 オブジェクトが 一 直 線 上 にあれば true, otherwise false. 2. Triangle クラスのメソッド: double computearea(); ベクトルの 内 積 を 用 いて 面 積 を 計 算 し 出 力 演 習 問 題 解 答 : その 詳 細 レベル 仕 様 をかくつもりで 1. クラス 名 クラスの 各 メンバーの 仕 様 2. 各 メンバーの 仕 様 : (a) 変 数 であれば その 型 (クラスもしくは 基 本 データ 型 ) およびその 役 割 機 能 の 説 明 をつける (b) メソッドであれば 出 力 およびパラメータ 型 を 明 記 した 上 で その 動 作 について 正 確 な 日 本 語 で 記 述 すること た だし (1) メソッド 中 で ( 別 のオブジェクトに 対 し)メソッド 呼 び 出 しを 行 う 場 合 はそのことも 明 記 (2) スタティックの 場 合 は static を 明 示 Java 言 語 の 構 文 で 書 けるなら なお 良 い 1. FAには {0, 1 の 入 力 記 号 系 列 が 与 えられる 2. 各 状 態 で 入 力 系 列 σ0σ1σn 1 (n は 入 力 系 列 長 )を 受 け 取 る 挙 動 は: (1) 先 頭 記 号 σ0 により 次 の 状 態 qnext を 決 め (2) qnext に 残 りの 入 力 系 列 σ1σn 1 を 渡 し 以 後 の 処 理 を 委 ねる 3. 入 力 系 列 が 空 列 ( 記 号 が 残 っていない n =0)のときは 最 終 状 態 なら 受 理 それ 以 外 の 場 合 は 非 受 理 のメッセージを 出 力 し 全 体 の 処 理 が 終 了 課 題 : FAの 動 作 を 模 倣 するプログラム(クラス State)を 書 くとして 必 要 なフィールドとメソッドを 与 え その 型 ならびにその 挙 動 を 説 明 せよ メソッド 中 で 別 のオブジェクトに 対 するメソッド 呼 び 出 しを 行 う 場 合 はそのことも 明 記 すること ヒント: 各 状 態 をエージェントと 考 える ただし 依 頼 先 ( 次 の 状 態 ) か ら 結 果 をもらう 必 要 はこの 場 合 ない 完 全 に 処 理 を 委 ねる 有 限 オートマトンは 演 習 でやったと 思 うが 自 動 販 売 機 の 状 態 遷 移 モデル 文 字 列 検 索 における 正 規 表 現 など 広 く 使 われている 35 36