Ssaw08 0930

56
SSAW08 後期第3回 Processingで オブジェクト指向プログラミング 2008年9月30日

Transcript of Ssaw08 0930

Page 1: Ssaw08 0930

SSAW08 後期第3回Processingでオブジェクト指向プログラミング2008年9月30日

Page 2: Ssaw08 0930

今日の課題

• Processingでオブジェクト指向プログラミング(OOP)について理解する• オブジェクトの概念を理解する• Processingでオブジェクト指向プログラミングをやってみる

Page 3: Ssaw08 0930

OOP理解のポイント

• OOP = 難しい?• OOPの難しげな用語たち

• オブジェクト• メソッド• メッセージ• 継承• 抽象化• カプセル化• ポリモーフィズム (多態性)• クラス• インスタンス化

• 言葉だけだとかなり難しそう…• 本質を理解すると、実はやっていることは単純

Page 4: Ssaw08 0930

プログラミング・パラダイムの変遷

• OOP以前:その1• 非構造化ログラミング

• 全てのコードが一つの連続したブロックに含まれている• アセンブリ言語・COBOL・BASICなど• goto文による制御• デバッグが難しい• 「スパゲティプログラム」

Page 5: Ssaw08 0930

プログラミング・パラダイムの変遷 実例:COBOLによるHello World

000100 IDENTIFICATION DIVISION.000200 PROGRAM-ID. HELLOWORLD.000300 DATE-WRITTEN. 02/05/96 21:04.000400* AUTHOR BRIAN COLLINS000500 ENVIRONMENT DIVISION.000600 CONFIGURATION SECTION.000700 SOURCE-COMPUTER. RM-COBOL.000800 OBJECT-COMPUTER. RM-COBOL.000900001000 DATA DIVISION.001100 FILE SECTION.001200100000 PROCEDURE DIVISION.100100100200 MAIN-LOGIC SECTION.100300 BEGIN.100400 DISPLAY " " LINE 1 POSITION 1 ERASE EOS.100500 DISPLAY "HELLO, WORLD." LINE 15 POSITION 10.100600 STOP RUN.100700 MAIN-LOGIC-EXIT.100800 EXIT.

Page 6: Ssaw08 0930

プログラミング・パラダイムの変遷

• OOP以前:その2• 手続型プログラミング

• 手続を呼び出す• サブルーチン、関数• C言語・FORTRAN・Pascal など• 3つの基本制御パターン

• 逐次処理• 分岐• 繰り返し

Page 7: Ssaw08 0930

プログラミング・パラダイムの変遷

• 手続型プログラミング、3つの基本制御パターン

判断

処理1 処理2

YesNo

処理1

処理2

判断

処理

Yes

No判断

処理

Yes

No

逐次処理 分岐 反復

Page 8: Ssaw08 0930

機能中心のソフトウェア開発の問題点

• 機能、手続きを中心に構成されたプログラムの問題点• プログラムの規模が大きくなるにつれて全体像の把握が難しい• 機能の追加・拡張・変更が難しい• コードの再利用が難しい• 規模が大きくなるにつれ、プログラミングにかかるコストが膨大に

• これらの欠点を改良するため、新たなパラダイムが考案される• オブジェクト指向プログラミング (OOP)

• Simula, Smalltalk, C++, Objective-C, Java, Python, Ruby, JavaScript, C# ...

• 「もの ( = オブジェクト)」の集まりとしてプログラムを構成する

Page 9: Ssaw08 0930

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

• オブジェクト指向プログラムのポイント:その1• 「もの (= オブジェクト)」という単位でプログラムを構成する

• オブジェクトは、属性(性質)とメソッド(動作・ふるまい)から構成

状態1状態2状態3

オブジェクト

メソッド1 メソッド2

メソッド3メソッド4

Page 10: Ssaw08 0930

• 例:「りんご」をオブジェクトとして考える

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

赤5.0甘い

ふじ

実がなる

成長する

落ちる腐る

青4.0

すっぱい

青リンゴ実がなる

成長する

落ちる腐る

Page 11: Ssaw08 0930

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

• オブジェクト指向プログラムのポイント:その2• オブジェクト同士がメッセージを送りあう

Page 12: Ssaw08 0930

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

• オブジェクト指向プログラムのポイント:その3• オブジェクトはメッセージを受け取り、それに応じた処理を行う

• メッセージの処理方法は、オブジェクト自身が知っていて、その処理はオブジェクトによって異なる (ポリモーフィズム)

getName()

オブジェクトA:人間

「田所 淳」

getName()

オブジェクトB:車

「トヨタカローラ」

Page 13: Ssaw08 0930

• オブジェクト指向プログラムのポイント:その4• 必要のない情報は隠す (カプセル化)

• プログラムの実装全てを知る必要はない• 必要なインターフェイス(接点)だけ見せて、あとは隠す

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

It’s this resemblance to real things that gives objects much of their power and appeal. They can notonly model components of real systems, but equally as well fulfill assigned roles as components insoftware systems.

Interface and Implementation

To invent programs, you need to be able to capture abstractions and express them in the programdesign. It’s the job of a programming language to help you do this. The language should facilitate theprocess of invention and design by letting you encode abstractions that reveal the way things work.It should let you make your ideas concrete in the code you write. Surface details shouldn’t obscurethe architecture of your program.

All programming languages provide devices that help express abstractions. In essence, these devicesare ways of grouping implementation details, hiding them, and giving them, at least to some extent,a common interface—much as a mechanical object separates its interface from its implementation, asillustrated in “Interface and Implementation” .

Figure 2-1 Inte rface and Im plem enta tion

910

11

87 6

implementationinterface

Looking at such a unit from the inside, as the implementor, you’d be concerned with what it’scomposed of and how it works. Looking at it from the outside, as the user, you’re concerned onlywith what it is and what it does. You can look past the details and think solely in terms of the rolethat the unit plays at a higher level.

The principal units of abstraction in the C language are structures and functions . Both, in differentways, hide elements of the implementation:

! On the data side of the world, C structures group data elements into larger units which can thenbe handled as single entities. While some code must delve inside the structure and manipulatethe fields separately, much of the program can regard it as a single thing—not as a collection ofelements, but as what those elements taken together represent. One structure can include others,so a complex arrangement of information can be built from simpler layers.

14 Inte rface and Im plem enta tion2007-12-11 | © 2007 Apple Inc. All Rights Reserved.

C H A P T E R 2

O bject-O riented P rogram m ing

インターフェイス 実装

Page 14: Ssaw08 0930

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

• オブジェクト指向プログラムのポイント:その5• オブジェクトから新たなオブジェクトを派生させることができる (継承)

植物

生物

動物

果物 穀物

りんご

ふじ 紅玉 デリシャス

バナナ マンゴー

Page 15: Ssaw08 0930

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

• クラス• クラスとは:オブジェクトの「型紙」• クラスをインスタンス化 (実体化) することでインスタンスオブジェクト

となる

色重さ(g)味

リンゴ(クラス)

実がなる

成長する

落ちる腐る

赤5.0甘い

ふじ(インスタンスオブジェクト)

実がなる

成長する

落ちる腐る

青4.0

すっぱい

青リンゴ(インスタンスオブジェクト)

実がなる

成長する

落ちる腐る

インスタンス化

Page 16: Ssaw08 0930

ProcessingでOOPを実践してみる!

• 簡単なクラスの作成から徐々に高度なアニメーションへ発展させてみる

• 丸い点を描くクラスを作ってみる• クラスに必要となる属性

属性 (型 変数名) 内容

float x 丸のx座標の位置

float y 丸のy座標の位置

float diameter 丸の直径

Page 17: Ssaw08 0930

丸を描く (クラスを使わない例)

• まずはクラスを使わないで、丸を描いてみる• setup() - 初期化• draw() - 画面の描画• グローバル変数として丸のパラメータを定義

• float x; → x座標• float y; → y座標• float diameter; → 直径

Page 18: Ssaw08 0930

丸を描く (クラスを使わない例)

int x = 150;int y = 200;int diameter = 30;

void setup() { size(400, 400); smooth(); noStroke();}

void draw() { background(0); ellipse(x, y, diameter, diameter);}

Page 19: Ssaw08 0930

丸を描く (クラスを使わない例)

Page 20: Ssaw08 0930

丸を描くクラスを宣言、属性を定義

• 丸を生成するクラスを宣言する• クラス名:Spot• インスタンスオブジェクト:sp

• Spotクラスをインスタンス化して、spというインスタンスオブジェクトを生成

• クラスの属性• float x; → x座標• float y; → y座標• float diameter; → 直径

Page 21: Ssaw08 0930

丸を描くクラスを宣言、属性を定義

• 現在のクラスをクラス図で表現

x: floaty: floatdiameter :float

Spot クラス名

属性

Page 22: Ssaw08 0930

丸を描くクラスを宣言、属性を定義

Spot sp; // クラスを宣言

void setup() { size(400, 400); smooth(); noStroke(); sp = new Spot(); // クラスの生成 (インスタンス化) sp.x = 150; // クラスの属性「x」に150を代入 sp.y = 200; // クラスの属性「y」に200を代入 sp.diameter = 30; // クラスの属性「diameter」に30を代入}

void draw() { background(0); ellipse(sp.x, sp.y, sp.diameter, sp.diameter);}

Page 23: Ssaw08 0930

丸を描くクラスを宣言、属性を定義

class Spot { float x, y; // x座標とy座標の位置 float diameter; // 円の直径}

Page 24: Ssaw08 0930

丸を描くメソッドを定義

• Spotクラスの「ふるまい (= メソッド)」を定義する• メソッドはクラス内で関数として表現される• 必要となるメソッド

• 円を描く• メソッド名

• void display()

Page 25: Ssaw08 0930

丸を描くメソッドを定義

• 現在のクラスをクラス図で表現

display(): void

x: floaty: floatdiameter :float

Spot クラス名

属性

メソッド

Page 26: Ssaw08 0930

丸を描くメソッドを定義

Spot sp;

void setup() { size(100, 100); smooth(); noStroke(); sp = new Spot(); sp.x = 33; sp.y = 50; sp.diameter = 30;}

void draw() { background(0); sp.display();}

Page 27: Ssaw08 0930

丸を描くメソッドを定義

class Spot { float x, y, diameter;

// display() メソッドを定義 void display() { ellipse(x, y, diameter, diameter); }}

Page 28: Ssaw08 0930

丸を描くコンストラクタを定義

• コンストラクタ (構築子、Constructor) とは• オブジェクトをインスタンス化する際に呼び出されて、内容の初期化な

どを行う関数• クラス名と同一の名前を持つメソッドとして定義される• 戻り値は持たない• コンストラクタに渡す引数により初期化のバリエーションが定義される

• 例:Spotクラスのコンストラクタ• Spot( 引数1, 引数2, 引数3 ...) { }

• Spotクラスの引数に以下の3つのパラメータを渡せるようにする• float x;• float y;• float diameter;

Page 29: Ssaw08 0930

丸を描くコンストラクタを定義

• 現在のクラスをクラス図で表現

Spot(xpos: float, ypos: float, diameter: float)display(): void

x: floaty: floatdiameter: float

Spot

Page 30: Ssaw08 0930

丸を描くコンストラクタを定義

Spot sp; //オブジェクトの宣言

void setup() { size(400, 400); smooth(); noStroke(); sp = new Spot(150, 200, 30); //コンストラクタ }

void draw() { background(0); sp.display();}

Page 31: Ssaw08 0930

丸を描くコンストラクタを定義

class Spot { float x, y, diameter; Spot(float x, float y, float diameter) { //クラスのインスタンス x(this.x) に、引数の値xを代入 this.x = x; //クラスのインスタンス y(this.y) に、引数の値yを代入 this.y = y; //diameter(this.diameter) に、引数の値diameterを代入 this.diameter = diameter; } void display() { ellipse(x, y, diameter, diameter); }}

Page 32: Ssaw08 0930

丸を動かしてみる

• さらにクラスを拡張して、丸をアニメーションさせてみる• 2つの属性と、1つのメソッドを追加する

• 追加する属性• 移動スピード

• float speed• 移動方向 (1を上向き、-1を下向きと解釈する)

• int speed

• 追加するメソッド• 座標移動

• void move()

Page 33: Ssaw08 0930

丸を動かしてみる

• クラス図を更新

Spot(xpos: float, ypos: float, diameter: float, speed:float)move(): voiddisplay(): void

x: floaty: floatdiameter: floatspeed: floatdirection: int

Spot

Page 34: Ssaw08 0930

丸を動かしてみる

Spot sp; //オブジェクトの宣言void setup() { size(400, 400); smooth(); noStroke(); sp = new Spot(150, 200, 30, 5); //インスタンス化}

void draw() { fill(0, 15); rect(0, 0, width, height); fill(255); sp.move(); //丸の座標を更新 sp.display(); //丸を表示}

Page 35: Ssaw08 0930

丸を動かしてみる

class Spot { float x, y; float diameter; float speed; //移動スピード int direction = 1; //移動の向き (1 下向き, -1 上向き) Spot(float xpos, float ypos, float dia, float sp) { x = xpos; y = ypos; diameter = dia; speed = sp; } void move() { //上下の端に到達した際に向きが反転する y += (speed * direction); if ((y > (height - diameter / 2)) || (y < diameter / 2)) { direction *= -1; } } void display() { ellipse(x, y, diameter, diameter); }}

Page 36: Ssaw08 0930

丸を動かしてみる

Page 37: Ssaw08 0930

複数のオブジェクトを配置する

• オブジェクトは、変数と同様に名前を変えて宣言することで複数宣言することが可能

• インスタンス化の際の引数を変化させることで、様々なバリエーションのSpotオブジェクトを同時に表示することができる

• Spotクラスから3つのオブジェクトを生成• sp1• sp2• sp3

Page 38: Ssaw08 0930

複数のオブジェクトを配置する

Spot sp1, sp2, sp3; //3つのオブジェクトを宣言void setup() { size(400, 400); smooth(); noStroke(); sp1 = new Spot(100, 200, 80, 2); //sp1を生成 sp2 = new Spot(200, 200, 20, 5); //sp2を生成 sp3 = new Spot(300, 50, 60, 3); //sp3を生成}void draw() { fill(0, 15); rect(0, 0, width, height); fill(255); sp1.move(); sp2.move(); sp3.move(); sp1.display(); sp2.display(); sp3.display();}

Page 39: Ssaw08 0930

複数のオブジェクトを配置する

class Spot { float x, y; float diameter; float speed; int direction = 1; Spot(float xpos, float ypos, float dia, float sp) { x = xpos; y = ypos; diameter = dia; speed = sp; } void move() { y += (speed * direction); if ((y > (height - diameter / 2)) || (y < diameter / 2)) { direction *= -1; } } void display() { ellipse(x, y, diameter, diameter); }}

Page 40: Ssaw08 0930

複数のオブジェクトを配置する

Page 41: Ssaw08 0930

より複雑な動きを作成する物理法則をシミュレート

• もっと複雑な動きに挑戦してみる• よりリアルな動きを実現できないか?• 簡単な物理法則をシミュレーションしてみる

• 重力• 摩擦• 反射

Page 42: Ssaw08 0930

Particleクラス

• Particleクラス• 重力の影響を受けながら運動する物体をシミュレート

• 必要となる属性• x座標、y座標 → float x, y;• x方向の速度、y方向の速度 → float vx, vy;• 大きさ → float radius;• 重力の強さ → float grabity;

• 必要となるメソッド• コンストラクタ → Particle• 座標の更新 → update• 画面に表示 → display

Page 43: Ssaw08 0930

Particleクラス

• Particleクラス、クラス図を作成

Particle(x:float, y:float, vx:float, vy:float, radius: float, gravity:float)update(): voiddisplay(): void

x: floaty: floatvx: floatvy: floatradius: floatgravity: float

Particle

Page 44: Ssaw08 0930

Particleクラス

class Particle { float x, y; float vx, vy; float radius; float gravity = 0.1; Particle(int x, int y, float vx, float vy, float radius) { this.x = x; this.y = y; this.vx = vx; this.vy = vy; this.radius = radius; } void update() { vy = vy + gravity; y += vy; x += vx; } void display() { ellipse(x, y, radius*2, radius*2); }}

Page 45: Ssaw08 0930

Particleを使用する

Particle p;

void setup() { size(400, 400); noStroke(); smooth(); p = new Particle(0, height, 2.5, -8, 10.0);}

void draw() { fill(0, 10); rect(0, 0, width, height); fill(255); p.update(); p.display();}

Page 46: Ssaw08 0930

Particleを表示する

Page 47: Ssaw08 0930

クラスの継承

• Particleクラスを継承して、別の性質を付加する

• Particleクラス• 画面からはみ出てもそのまま落下していく• 画面の範囲でバウンドするように変更したい

• LimitedParticleクラス• Particleクラスを継承• 画面の範囲内でバウンドする• 常に一定の割合で摩擦の影響を受ける

Page 48: Ssaw08 0930

LimitedParticleクラスの実装

• クラス図• Particleクラスと、それを継承するLimitedParticleクラス

Particle(x:float, y:float, vx:float, vy:float, radius: float, gravity:float)update(): voiddisplay(): void

x: floaty: floatvx: floatvy: floatradius: floatgravity: float

Particle

LimitedParticle(x:float, y:float, vx:float, vy:float, radius: float, gravity:float, friction:float)update(): voidlimit(): void

friction: float

LimitedParticle

Page 49: Ssaw08 0930

LimitedParticleクラス

class LimitedParticle extends Particle { float friction = 0.99; LimitedParticle(int x, int y, float vx, float vy, float radius, float friction) { super(x, y, vx, vy, radius); //親クラスの引数を参照 this.friction = friction; //摩擦係数 } void update() { vy *= friction; vx *= friction; super.update(); // limit(); } void limit() { //表示範囲内でバウンドする if (y > height - radius) { vy = -vy; y = constrain(y, -height * height, height - radius); } if ((x < radius) || (x > width - radius)) { vx = -vx; x = constrain(x, radius, width - radius); } }}

Page 50: Ssaw08 0930

LimitedParticleクラスを使用する

int num = 80;LimitedParticle[] p = new LimitedParticle[num];float radius = 1.2;void setup() { size(640, 480); noStroke(); smooth(); for (int i = 0; i < p.length; i++) { float velX = random(-4, 4); float velY = random(-10, 0); p[i] = new LimitedParticle(width/2, height/2, velX, velY, 2.2, 0.999); }}void draw() { fill(0, 24); rect(0, 0, width, height); fill(255); for (int i = 0; i < p.length; i++) { p[i].update(); p[i].display(); }}

Page 51: Ssaw08 0930

LimitedParticleクラスを使用する

Page 52: Ssaw08 0930

色の付加

• LimitedParticleクラスに色の属性を追加する• 色の属性

• color col;• 設定した色で塗るように、display() メソッドを拡張

• super.display() を実行• スーパークラス (Particle) の display() メソッドの呼びだし

• 色の指定の付加

Page 53: Ssaw08 0930

色の付加

• クラス図追加

Particle(x:float, y:float, vx:float, vy:float, radius: float, gravity:float)update(): voiddisplay(): void

x: floaty: floatvx: floatvy: floatradius: floatgravity: float

Particle

LimitedParticle(x:float, y:float, vx:float, vy:float, radius: float, gravity:float, friction:float, col:color)update(): voidlimit(): voiddisplay(): void

friction: floatcol: color

LimitedParticle

Page 54: Ssaw08 0930

色の付加

class LimitedParticle extends Particle { float friction = 0.99; color col; //色の属性 LimitedParticle(int x, int y, float vx, float vy, float radius, float friction, color col) { super(x, y, vx, vy, radius); this.friction = friction; this.col = col; } void update() { vy *= friction; vx *= friction; super.update(); limit(); } void limit() { if (y > height - radius) { vy = -vy; y = constrain(y, -height * height, height - radius); } if ((x < radius) || (x > width - radius)) { vx = -vx; x = constrain(x, radius, width - radius); } } void display() { fill(col); super.display(); //スーパークラス (Particle) の display() を呼び出し }}

Page 55: Ssaw08 0930

色の付加

int num = 200;LimitedParticle[] p = new LimitedParticle[num];float radius = 1.2;void setup() { size(640, 480); colorMode(HSB,360,100,100,100); //HSBで色を指定する noStroke(); smooth(); for (int i = 0; i < p.length; i++) { float velX = random(-4, 4); float velY = random(-10, 0); color col = color(random(180,240),random(50,100),50); //ランダムに色指定 p[i] = new LimitedParticle(width / 2, height / 2, velX, velY, 2.2, 0.9999, col); }}void draw() { fill(0, 10); rect(0, 0, width, height); fill(255); for (int i = 0; i < p.length; i++) { p[i].update(); p[i].display(); }}

Page 56: Ssaw08 0930

色の付加