計算機プログラミングI 第10回 データ構造とクラスの設計 例題: 話題: 複素数 図形要素 Morphing 複雑な値を一つにまとめる

Slides:



Advertisements
Similar presentations
オブジェクト指向 言語 論 第八回 知能情報学部 新田直也. 多相性(最も単純な例) class A { void m() { System.out.println( “ this is class A ” ); } } class A1 extends A { void m() { System.out.println(
Advertisements

ソフトウェア工学 知能情報学部 新田直也. オブジェクト指向パラダイムと は  オブジェクト指向言語の発展に伴って形成され てきたソフトウェア開発上の概念.オブジェク ト指向分析,オブジェクト指向設計など,プロ グラミング以外の工程でも用いられる.  ソフトウェアを処理や関数ではなくオブジェク.
6.4継承とメソッド 6.5継承とコンストラクタ 11月28日 時田 陽一
情報処理演習 (9)グラフィックス システム科学領域 日浦 慎作.
プログラミング言語としてのR 情報知能学科 白井 英俊.
~手続き指向からオブジェクト指向へ(Ⅰ)~
第12回新しい型と構造体.
第13回構造体.
プログラミングパラダイム さまざまな計算のモデルにもとづく、 プログラミングの方法論 手続き型 関数型 オブジェクト指向 代数 幾何.
解答 1 複素数を構造体として定義し、二つの複素数の積(結果は複素数)を返す 関数 を定義せよ。
第12回構造体.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
アルゴリズムとデータ構造1 2007年6月12日
アルゴリズムとプログラミング (Algorithms and Programming)
地理情報システム論 第3回 コンピュータシステムおける データ表現(1)
基礎プログラミング (第五回) 担当者: 伊藤誠 (量子多体物理研究室) 内容: 1. 先週のおさらいと続き (実習)
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミングIII演習 第1回目.
オブジェクト指向入門.
ピカチュウによる オブジェクト指向入門 (新版)
計算機プログラミングI 第8回 2002年12月5日(木) メソッドとクラス (教科書6章) クイズ インスタンスメソッド インスタンス変数
第6回独習Javaゼミ 第6章 セクション4~6 発表者 直江 宗紀.
プログラミング 3 構造体(1).
プログラミング演習3 第2回 GUIの復習.
ソフトウェア工学 知能情報学部 新田直也.
プログラミング言語入門 手続き型言語としてのJava
アルゴリズムとプログラミング (Algorithms and Programming)
オブジェクト指向 プログラミング 第十一回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
第10回関数 Ⅱ (ローカル変数とスコープ).
第11週:super/subクラス、継承性、メソッド再定義
プログラミング演習3 第2回 GUIの復習.
計算機プログラミングI 第11回 再帰 再帰的なメソッド定義 帰納的定義 再帰的なデータ構造 計算機プログラミングI (増原) 2003年度.
C#言語ソースプログラムの原型 C言語 C#言語 Hello World! Hello Students! オマジナイ! 適当なクラス名
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向 プログラミング 第十ニ回 知能情報学部 新田直也.
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
計算機プログラミングI 第5回 配列 文字列(Stringクラス) mainの引数 配列の利用例
計算機プログラミングI 第8回 素数を見つけるアルゴリズム 継承とインスタンスメソッド クラスの設計 オブジェクトに機能を加える
計算機プログラミングI 第12回 スレッド インターフェース 授業アンケート 計算機プログラミングI (増原) 2003年度.
第8回放送授業.
オブジェクト プログラミング 第2回 プログラムの基本.
アルゴリズムとプログラミング (Algorithms and Programming)
プログラミング言語論 第十三回 理工学部 情報システム工学科 新田直也.
ソフトウェア工学 知能情報学部 新田直也.
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
C#プログラミング実習 第3回.
計算機プログラミングI 木曜日 1時限・5時限 担当: 増原英彦 第1回 2002年10月10日(木)
計算機プログラミングI 第3回 プリミティブ値 クラスメソッド クラス変数 式と演算 変数の利用
アルゴリズムとプログラミング (Algorithms and Programming)
画面への描画 Graphics オブジェクト 紙 ペン Pen オブジェクト Brush オブジェクト 画面のピクセルをカプセル化
計算機プログラミングI 第4回 2002年10月31日(木) 問題解決とアルゴリズム クラスメソッドと手続きの抽象化 最大公約数
モグラたたき.
メンバとメソッド C言語の構造体 変数の集まり C#言語のクラス + それを処理する関数の集まり フィールド または メンバ変数 メンバ
オブジェクト指向言語論 第十一回 知能情報学部 新田直也.
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
cp-3. 計算 (C プログラミング演習,Visual Studio 2019 対応)
ソフトウェア工学 知能情報学部 新田直也.
オブジェクト指向言語論 第七回 知能情報学部 新田直也.
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
オブジェクト指向言語における セキュリティ解析アルゴリズムの提案と実現
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
オブジェクト指向言語論 第十回 知能情報学部 新田直也.
C言語講座第5回 2017 構造体.
計算機プログラミングI 第2回 2002年10月17日(木) 履習登録 複習 ライブラリの利用 (2.6-7) 式・値・代入 (2.6-8)
計算機プログラミングI 第10回 2002年12月19日(木) メソッドの再定義と動的結合 クイズ メソッドの再定義 (オーバーライド)
計算機プログラミングI 第5回 2002年11月7日(木) 配列: 沢山のデータをまとめたデータ どんなものか どうやって使うのか
Presentation transcript:

計算機プログラミングI 第10回 データ構造とクラスの設計 例題: 話題: 複素数 図形要素 Morphing 複雑な値を一つにまとめる 似たような値を統一的に扱う 中身を気にしないで扱いたい 計算機プログラミングI (増原) 2003年度

複雑な値を一つにまとめる プログラム中で扱うモノ 整数・タートル・複素数・図形要素・・・ 複数の値の組み合わせで表わされるモノも多い プログラム中で扱うモノ 整数・タートル・複素数・図形要素・・・ 複数の値の組み合わせで表わされるモノも多い タートル = X,Y座標,方向,色,ペン状態,… 複素数 = 実・虚成分 直線 = 両端点のX,Y座標 各値をバラバラに扱うのは大変 → 1つの値として扱いたい (変数に代入・引数・・・) → オブジェクトとして表現 計算機プログラミングI (増原) 2003年度

例題: マンデルブロ集合を表示したい 直感的なアルゴリズム: 複素関数 f(c,z) = z2+c が与えられた場合 z0=0としてi=0,1,2,…,29まで繰り返す |zi|>2となったら 繰り返しを止める zi+1=zi2+cとする 繰り返しの回数に 応じた色をc上に塗る オブジェクトを用いない プログラム for(c_real=…) for(c_imag=…) z_real=0, z_imag=0; for (k=0;k<30;k++) { mag = sqrt(z_real*z_real +z_imag*z_imag); if (mag<2) break; z_sq_real=z_real*z_real -z_imag*z_imag; z_sq_imag=2*z_real*z_imag; z_real = z_sq_real+c_real; z_imag = z_sq_imag+c_imag; } 計算機プログラミングI (増原) 2003年度

複素数をクラスとして表わす 「複素数」という1つの数を 「1つのオブジェクト」として表わそう!  クラスを定義する 「複素数」という1つの数を 「1つのオブジェクト」として表わそう!  クラスを定義する 複素数という1つの数を簡単に作れるようにしよう  コンストラクタを定義する 複素数に関する計算は複素数クラスに定義しよう  インスタンスメソッドを定義する 複素数の表現形式を使い分けよう  継承を利用する 計算機プログラミングI (増原) 2003年度

複素数: クラスの定義 /** 複素数 */ class Complex { インスタンス変数・ インスタンスメソッド・ 複素数オブジェクトの性質の定義 = クラスの定義 名前 : Complex /** 複素数 */ class Complex { インスタンス変数・ インスタンスメソッド・ コンストラクタの定義 } 計算機プログラミングI (増原) 2003年度

複素数: インスタンス変数の定義 複素数のベクトル表現: x+yi → 2つの実数 → 2つの実数型インスタンス変数 class Complex { public double real; // 実部 public double imag; // 虚部 インスタンスメソッド・ コンストラクタの定義 } Complex c = new Complex(); c.real = 1; c.imag = 2; 計算機プログラミングI (増原) 2003年度

複素数:コンストラクタの定義 Complex c = new Complex(1,2); のようにしたい class Complex { public double real; // 実部 public double imag; // 虚部 /** 実部, 虚部から複素数を作る */ public Complex(double r, double i) { real = r; imag = i; } 計算機プログラミングI (増原) 2003年度

複素数の演算とメソッド 複素数どうしの演算 (乗算、加算、etc.) を どのように定義するか? (例: z*c) 方針1: 新しく複素数の値を作って返す 例: zとcの積は新しいオブジェクト。zやcはそのまま 数学的。z*c+(z*z+c)のような計算が素直に書ける 方針2: メソッド呼び出しを受けたオブジェクトの 状態を変化 例: zの新しい状態がz*cになる オブジェクトが何かの実体に対応している場合に便利 (例: タートル・図形要素・etc.) 計算機プログラミングI (増原) 2003年度

複素数:インスタンスメソッドの定義 public Complex add(Complex y) { class Complex { インスタンス変数・ コンストラクタの定義 public Complex add(Complex y) { double r = real + y.real; //実部の計算 double i = imag + y.imag; //虚部の計算 return new Complex(r,i); //新しい複素数を作って返す } Complex c1 = new Complex(1,2); Complex c2 = new Complex(3,4); Complex c3 = c1.add(c2); 計算機プログラミングI (増原) 2003年度

例題: マンデルブロ集合 オブジェクトを用いた プログラム オブジェクトを用いない プログラム for(c_real=…) for(c_imag=…) c = new Complex(c_real,c_imag); z = new Complex(0,0); for (k=0;k<30;k++) { if (z.mag()<2) break; z = z.mul(z).add(c); } オブジェクトを用いない プログラム for(c_real=…) for(c_imag=…) z_real=0, z_imag=0; for (k=0;k<30;k++) { mag = sqrt(z_real*z_real +z_imag*z_imag); if (mag<2) break; z_sq_real=z_real*z_real -z_imag*z_imag; z_sq_imag=2*z_real*z_imag; z_real = z_sq_real+c_real; z_imag = z_sq_imag+c_imag; } 計算機プログラミングI (増原) 2003年度

似たような値を統一的に扱う 異なるけど統一的に扱いたい値 → 継承を活用する 例: 図形要素の線と円は違うモノだけど 「表示する」「距離を求める」等は同様に行いたい → 継承を活用する 共通する性質・操作は親クラスに定義 個別の操作内容は子クラスのメソッドで再定義 個別の性質・操作は子クラスに(追加定義) → 「同様に行いたい」部分は親クラスのオブジェクトとして扱うことができる 計算機プログラミングI (増原) 2003年度

図形要素 図形エディタの中の個々の要素 (線や円など)を どのようにして扱うか? ―― 行う操作を考える 例: マウスによる消去 1. 画面上の1点を選ぶ 2. その点に最も近い図形要素を見つける 3. 画面を消す 4. 全ての図形要素(ただし2で見つけたもの以外)を再描画する 図形要素を単位として操作→オブジェクト 統一して行いたい(だけど図形ごとに違う)操作: 距離を求める 画面に表示する 計算機プログラミングI (増原) 2003年度

共通図形要素のクラス定義 とりあえず共通するクラスを作り、 共通して存在すべき操作をメソッドとして定義 public class FigureElement { public void draw(Turtle m) {} public double distance(int x, int y) { return 0; } 計算機プログラミングI (増原) 2003年度

個々の図形要素のクラス定義 public class FigureElement { public void draw(Turtle m) {} public double distance(int x, int y) { return 0; } public class Point extends FigureElement { int x, y; public void draw(Turtle m) { … } public double distance(int x, int y) { …; } public class Line extends FigureElement { インスタンス変数 public void draw(Turtle m) { … } public double distance(int x, int y) { …; } 計算機プログラミングI (増原) 2003年度

図形要素を使う側のプログラム 使う側はどのような 図形要素かを気にせずに距離を求め、再描画できる。 図形要素が増えても、この部分は変更不用! FigureElement[] figs = …; int numFigs = …; /* x,y に最も近い図形を見つける*/ double minDist = MAX; for (int i=0; i<numFigus; i++) { if (figs[i].distance(x,y) < minDist) { …} } //見つけた図形要素を取り除く(略) //再描画 for (int i= …) figs[i].draw(m); public class FigureElement { public void draw(Turtle m) {} public double distance(int x, int y) { return 0; } 使う側はどのような 図形要素かを気にせずに距離を求め、再描画できる。 図形要素が増えても、この部分は変更不用! 計算機プログラミングI (増原) 2003年度

何が共通? 何が個有? 色: 全てに共通 回転・拡大: 設計による 時にはクラスの設計を1からやり直す必要も FigureElementのインスタンス変数 個々のdrawメソッド 回転・拡大: 設計による 回転角や拡大率を共通の性質として持たせる 拡大すると個々の状態(例えば線分の座標)を変化 時にはクラスの設計を1からやり直す必要も public class FigureElement { public void draw(Turtle m) {} public double distance(int x, int y) { return 0; } public class Point extends FigureElement { int x, y; public void draw(Turtle m) { … } public double distance(int x, int y) { …; } public class Line extends FigureElement { インスタンス変数 public void draw(Turtle m) { … } public double distance(int x, int y) { …; } 計算機プログラミングI (増原) 2003年度

中身を気にしたくない 複雑な値の詳細を気にせずに扱いたい 例: タートルの座標が整数か実数か 例: 複素数は直交座標か極形式か 例: 直線は「両端点」か「1点と幅・高さ」か「1点と方向・長さ」か → インスタンスメソッドを通してのみ オブジェクト状態を得るようにプログラムを書くと クラス定義の中身を変えても大丈夫 計算機プログラミングI (増原) 2003年度

一つの値、二つの表現 複素数の表わし方には二つある: y r q x 直交座標系: 実部と虚部の成分の組 x+iy 極形式: reiq

2つの複素数クラス 直交座標系 class Complex { double real, imag; double getReal() {return real;} double getImag() {return real;} double getMag() { … } double getAng() { … } Complex add(Complex c) { … } Complex mul(Complex c) { … } … } 極形式 class Complex { double mag, theta; double getReal() { … } double getImag() { … } double getMag() { return mag; } double getAng() { return theta; } Complex add(Complex c) { … } Complex mul(Complex c) { … } … } 使う側は同じプログラムでOK for(c_real=…) for(c_imag=…) c = new Complex(c_real,c_imag); z = new Complex(0,0); for (k=0;k<30;k++) { if (z.mag()<2) break; z = z.mul(z).add(c); } 計算機プログラミングI (増原) 2003年度

一つの値、二つの表現 複素数の表わし方には二つある: それぞれ向き、不向きがある 二つの表現のイイトコドリをしたい! → 2つの複素数クラス 直交座標系: 実部と虚部の成分の組 x+iy 極形式: reiq それぞれ向き、不向きがある 直交座標系: 和・差 (成分ごと) 極形式: 積・商・絶対値 (絶対値の積・商,偏角の和・差) 二つの表現のイイトコドリをしたい! → 2つの複素数クラス y r q x 計算機プログラミングI (増原) 2003年度

一つの値、二つの表現 複素数の表わし方には二つある: それぞれ向き、不向きがある 二つの表現のイイトコドリをしたい! → 2つの複素数クラス 直交座標系: 実部と虚部の成分の組 x+iy 極形式: reiq それぞれ向き、不向きがある 直交座標系: 和・差 (成分ごと) 極形式: 積・商・絶対値 (絶対値の積・商,偏角の和・差) 二つの表現のイイトコドリをしたい! → 2つの複素数クラス y r q x 計算機プログラミングI (増原) 2003年度

2つの複素数クラス 共通の性質・操作 実部・虚部などを 求める 四則演算 直交座標系 極形式 class Comlpex { double getReal() {…} double getImag() {…} double getMag() {…} double getAng() {…} Complex add(Complex c) { … } … } 直交座標系 極形式 class CartesianComplex extends Complex { double real, imag; double getReal() { … } } class PolarComplex extends Complex { double mag, theta; dobule getReal() { … } } 計算機プログラミングI (増原) 2003年度

2つの複素数クラス 共通の性質 実部・虚部などを 求める――個別 四則演算―― 共通 直交座標系 極形式 class Comlpex { …略… Complex add(Complex c) { return new CartesianComlpex( this.getReal()+c.getReal(), this.getImag()+c.getImag());} Complex mul(Complex c) { return new PolarComplex( this.getMag()*c.getMag(), this.getAng()+c.getAng());} } 直交座標系 極形式 class PolarComplex extends Complex { double mag, theta; dobule getReal() { return mag*cos(theta);} } class CartesianComplex extends Complex { double real, imag; double getReal() { return real;} } 計算機プログラミングI (増原) 2003年度

2つの複素数を使う人は? 使う人はどっちの表現かを気にしなくてもよい! class Comlpex { double getReal() {…} double getImag() {…} double getMag() {…} double getAng() {…} Complex add(Complex c) { … } … } Complex c1 = new CatesianComplex(1,2); Complex c2 = new PolarComplex(0,PI/2); Complex c3 = c1.add(c2).mul(c2); if (c3.getMag() < 2) … 使う人はどっちの表現かを気にしなくてもよい! 計算機プログラミングI (増原) 2003年度

おまけ 継承でひろがる可能性 計算機プログラミングI (増原) 2003年度

Morphing再び Morphingのためのコード 中間の位置を計算し、 その位置へタートルを移動させる 中間の位置を計算し、 その位置へタートルを移動させる for(i = 0; i < steps; i++){ mc (円)を移動 ms (星形)を移動 mm.moveTo((mc.getX()+ms.getX())/2, (mc.getY()+ms.getY())/2, 0); } 計算機プログラミングI (増原) 2003年度

オブジェクト指向によるMorphing 中間の図形を描くタートルは 追いかけるタートルを知っている 星 追いかけろ、と指示を受けると 自ら中間地点へ移動 星 円 for(i = 0; i < steps; i++){ mc (円)を移動 ms (星形)を移動 mm.step(); } Morph 計算機プログラミングI (増原) 2003年度

Morphクラスの設計 Turtleクラスを拡張 追いかける対象 →インスタンス変数 public class Morph extends Turtle { // 追いかける対象 Turtle m1, m2; コンストラクタ・インスタンスメソッドの定義 } 計算機プログラミングI (増原) 2003年度

Morph: コンストラクタ Morph m = new Morph(mCircle, mStar); のようにしたい public class Morph extends Turtle { public Turtle m1, m2; public Morph(Turtle m1, Turtle m2) { this.m1 = m1; this.m2 = m2; } インスタンスメソッドの定義 計算機プログラミングI (増原) 2003年度

Morph:インスタンスメソッド m.step() とすると、m1 と m2 の中間へ移動 public void step() { public class Morph extends Turtle { public Turtle m1, m2; コンストラクタ(略) public void step() { 自身をm1とm2の中間に移動 } 計算機プログラミングI (増原) 2003年度

Morphクラスの使用 使う側は「どうやって中間の位置を 追いかけているか」を気にしなくてよい Turtle mc = new Turtle(); Turtle ms = new Turtle(); Morph mm = new Morph(mc,ms); for(i = 0; i < steps; i++){ mc (円)を移動 ms (星形)を移動 mm.step(); } 使う側は「どうやって中間の位置を 追いかけているか」を気にしなくてよい 計算機プログラミングI (増原) 2003年度

Morphクラスの使用 星 円 Morph m0 = new Morph(mc,ms); m0 Turtle mc = new Turtle(); Turtle ms = new Turtle(); Morph m0 = new Morph(mc,ms); Morph m1 = new Morph(mc,m0); Morph m2 = new Morph(m0,ms); for(i = 0; i < steps; i++){ mc (円)を移動 ms (星形)を移動 m0.step(); m1.step(); m2.step(); } m0 m2 m1 「Morphオブジェクトを追いかけるMorphオブジェクト」 も可能 ← MorphはTurtleの子クラス 計算機プログラミングI (増原) 2003年度

Morphingの発展 各タートルはstepメソッドを呼び出されると、 各自、自分のやり方で適当な図を描くとする(T61.java) 組み合わせれば stepによって星を描くタートルがあれば円と星のMorphing 手書きの図を覚えるタートルを作り、stepメソッドで再生するようにしておけば、手書き図のMorphing フラクタル図形をstepごとに描くタートルがあればフラクタル図形のMorphing 必要なもの? ―― 共通の親クラス 計算機プログラミングI (増原) 2003年度