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

5.3.5 クラスファイルの作成

ここでは、他のプログラムにも再利用できるようにCircleクラス用のファイルを作成します。コードは【リスト5.3-b】をコピーし、そこからCircleクラスの部分だけを別ファイル(Circle.pde)にします。

Processingの画面右上のボタンから「New Tab」をクリックします【図5.3-g】。

2016_09_30_2_31
図5.3-g

さらに、この新しいタブの名前をクラス名であるCircleにして「OK」します【図5.3-h】。

2016_09_30_2_18
図5.3-h

すると、新しいファイルが表示されます【図5.3-i】。

2016_09_30_2_26
図5.3-i

Circleクラスをファイルにする場合には、ファイル名は必ずクラス名と同じになっていなければいけません。このサンプルでは、次のふたつのファイルに分けました【図5.3-j】。

・【リスト5.3-f】フォルダ

・oop_class.pde(実行ファイル)
・Circle.pde(クラスファイル)

この新しいCircleクラスのファイルに、クラスの定義の部分だけカット&ペーストして保存します。実行ファイル(oop_class.pde)にクラス定義のコードを残さないでください。

2016_09_30_2_27
図5.3-j

ファルダ構成は【図5.3-k】のようになります。

2017_01_02_14_17
図5.3-k

これでクラスファイルの作成は終了です。一度クラスファイルを作ったら、それ以降はSketchメニュー > Add File…で他のプログラムで再利用することができます。

完成したファイル【リスト5.3-f】 ダウンロード

5.3.6 クラスの継承とは

ここからは、オブジェクトに柔軟性と拡張性を与えるための機能である「継承」を学びます。
継承は、簡単に言ってしまえば「遺伝」です。親から子が産まれる時に親のDNAを引き継ぎますが、完全な親のコピーではありません。新たな能力の獲得がある場合もありますし、それぞれ違った個性が育ちます。
このように、クラスがひな型だとすると、そのひな型の属性を引き継ぎなおかつ新しい属性を付加したクラスを作成することを「継承」と呼びます。

inheritence
図5.3-l

5.3.7 クラスの合成

クラスの継承の前に、複数のクラスを合成したクラスを作ってみます。サンプルでは、正方形と円の複合体が作成されます。

2016_09_30_3_00
図5.3-m

まず、前述の「oop_class.pde」を「oop_circle_rect」として別名保存してください。さらにこの他にクラスファイルを3つ作るので、ファイルは全部で4つになります。

・【リスト5.3-g】フォルダ

・oop_circle_rect.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – 再利用)
・Rect.pde(クラスファイル – 新規)
・CircleRect.pde(クラスファイル – 新規)

それでは、一つずつ作っていきましょう。まず、Rectクラスを作ります。

Rect.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Rect { 
  float x, y;    //x座標、y座標
  float rad;    //正方形の回転角度
  int rSize;    //正方形のサイズ
  float velocity;    //移動スピード
 
  //コンストラクタ
  Rect(float _y, int _rSize, float _velocity) {
    rectMode(CENTER);    //基準点を正方形の中心にする
    x = 0.0;  
    y = _y;
    rad = 0.0;
    rSize = _rSize;
    velocity = _velocity;
  }
 
  //更新メソッド
  void update() { 
    noFill();
 
    x += velocity;    //velocity分のx座標を移動
    if (x > width) {    //円のx座標がウィンドウの幅を超えたら、
      x = 0;    //位置を0に戻す
    }
  }
 
  //表示メソッド
  void display() {   
    pushMatrix();    //座標を保存
    translate(x, y);    //基準点を移動
    rotate(rad);    //回転
    rect(0, 0, rSize, rSize);    //正方形を描画
    popMatrix();    //座標を復帰
    rad += 0.01;
  }
}

さらに、CircleクラスとRectクラスを合成した、CircleRectクラスを作成します。

CircleRect.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class CircleRect {
  Circle myCircle;  //インスタンス
  Rect myRect;
 
  //コンストラクタ
  CircleRect(float _y, int _eSize, int _rSize, float _velocity) {
    //Circleクラスのインスタンスを作成
    myCircle = new Circle(_y, _eSize, _velocity);
 
    //Rectクラスのインスタンスを作成    
    myRect = new Rect(_y, _rSize, _velocity);
  }
 
  void display() {
    myCircle.update();    //更新と表示
    myCircle.display();
    myRect.update();
    myRect.display();
  }
}

CircleRectクラスの中でCircleクラスとRectクラスのインスタンスを作成しています。
このCircleRectクラスを最終的に、opp_circle_rectファイル(実行ファイル)内でインスタンス化します。

opp_circle_rect.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CircleRect cr1, cr2;    //CircleRectクラスのインスタンスを宣言
 
void setup() {
  size(400, 400);
  stroke(0);
 
  //引数はCircleRect(y座標, ellipseのサイズ、rectのサイズ、スピード)
  cr1 = new CircleRect(100, 5, 20, 0.1);    //オブジェクトを作成
  cr2 = new CircleRect(300, 40, 60, 0.3);    //オブジェクトを作成
}
 
void draw() {
  background(255);    //背景は白
  cr1.display();    //c1, c2インスタンスのupdateメソッドを実行
  cr2.display();
}

完成したファイル【リスト5.3-g】 ダウンロード

5.3.8 クラスの継承

さて、ここからがクラスの継承の本番です。Circleクラスはそのまま使いますが、このクラスを継承して色彩の機能を持たせたColorCircleクラスを作成します。最終的には別々の色彩を持った円を作成します。

10_4_15__1_09_AM
図5.3-n

作成するファイルは次の3つです。

・【リスト5.3-h】フォルダ

・oop_color_circle.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – 再利用)
・ColorCircle.pde(クラスファイル – 新規)

ColorCircle.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//Circleクラスを継承したColorCircleクラス
class ColorCircle extends Circle {
  color eColor;    //色彩の変数であるeColorを宣言
 
  //コンストラクタ
  ColorCircle (float _y, int _eSize, float _velocity, color _eColor) { 
    //親クラス(Circleクラス)のコンストラクタを実行する
    super(_y, _eSize, _velocity);
    eColor = _eColor;
  }
 
  //更新メソッド
  void update() {
    super.update();  //親クラス(Circleクラス)のupdate()メソッドを実行
  }
 
  //色を設定して表示するメソッド
  void displayColor() {
    fill(eColor);    //色彩を設定
    super.display();  //親クラス(Circleクラス)のdisplay()メソッドを実行
  }
}

このクラスを宣言することによって、円の色を定義することが可能になりました。
この場合のCircleクラスを親クラス(スーパークラス)、ColorCircleクラスを子クラス(サブクラス)と呼びます。親子の関係となっているということですね。
そして、最終的にoop_color_circleファイルでColorCircleクラスのインスタンスを作成します。

oop_color_circle.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ColorCircle c1, c2;    //ColorCircleクラスのインスタンスを宣言
 
void setup() { 
  size(400, 400);
  noStroke();
  fill(0);    //黒で描画
 
  //インスタンス作成
  c1 = new ColorCircle(100, 10, 1.0, color(255, 0, 0));
  c2 = new ColorCircle(300, 40, 3.5, color(0, 0, 255));
}
 
void draw() {
  background(255);    //背景は白
 
  //c1インスタンスのクラスである、ColorCircleクラスのupdate()と
  //displayColor()メソッドを実行
  c1.update(); 
  c1.displayColor();
 
  c2.update(); 
  c2.displayColor();
}

完成したファイル【リスト5.3-h】 ダウンロード

5.3.9 クラスのカスタマイズ

それではもう少しクラスの作成に慣れるためにoop_color_circleサンプルを元に、キーボードの矢印キーでオブジェクトのスピードが変わるように書き換えてみましょう。まずは、Circleクラスにスピードを設定するメソッド(setVelocity)を追加します。

・【リスト5.3-i】フォルダ

・oop_circle_velocity.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – メソッド追加)
・ColorCircle.pde(クラスファイル – メソッド追加)

Circle.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//Circleクラスの宣言
class Circle {
 
  float x, y, eSize, velocity;
 
  //初期化用メソッド(コンストラクタ) 
  Circle (float _y, int _eSize, float _velocity) {
 
    x = 0.0;    //x座標の初期値は0.0
    y = _y;     //y座標の初期値はインスタンスの引数
    eSize = _eSize;
    //velocityの初期値はインスタンスの引数
    velocity = _velocity;
  }
 
  //円の位置を更新するメソッド
  void update() {
 
    x += velocity;    //velocity分のx座標を移動
    if (x > width) {    //円のx座標がウィンドウの幅を超えたら、
      x = 0;    //位置を0に戻す
    }
  }
 
  void display() {
    ellipse(x, y, eSize, eSize);    //円を描く
  }
 
  //スピードを設定するメソッド
  void setVelocity(float _velocity) {
 
    velocity += _velocity;
    //0未満にはならないようにする
    if (velocity < 0.0) velocity = 0.0;
  }
}

そして、ColorCircleクラスに、スピードを変えるfaster(), slower()メソッドを追加します。

ColorCircle.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//Circleクラスを継承したColorCircleクラス
class ColorCircle extends Circle {
  color eColor;    //色彩の変数であるeColorを宣言
 
  //コンストラクタ
  ColorCircle (float _y, int _eSize, float _velocity, color _eColor) {
 
    //親クラス(Circleクラス)のコンストラクタを実行する
    super(_y, _eSize, _velocity);
    eColor = _eColor;
  }
 
  //更新メソッド
  void update() {
 
    super.update();  //親クラス(Circleクラス)のupdate()メソッドを実行
  }
 
  //色を設定して表示するメソッド
  void displayColor() {
 
    fill(eColor);    //色彩を設定
    super.display();  //親クラス(Circleクラス)のdisplay()メソッドを実行
  }
 
  //スピードを速くするメソッド
  void faster() {
 
    //親クラス(Circleクラス)のsetvelocity()に0.5を渡す
    super.setVelocity(0.5);
  }
 
  //スピードを遅くするメソッド
  void slower() {
 
    //親クラス(Circleクラス)のsetvelocity()に-0.5を渡す
    super.setVelocity(-0.5);
  }
}

最後に、oop_circle_velocityには、keyPressed()の機能を追加します。

リスト5.3-m

oop_circle_velocity.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
//ColorCircleクラスのインスタンスを宣言
ColorCircle c1, c2;
 
void setup() {
 
  size(400, 400);
  smooth();    //図形の輪郭をきれいに描画
  noStroke();
  fill(0);    //黒で描画
 
  //インスタンス作成
  c1 = new ColorCircle(100, 10, 1.0, color(255, 0, 0));
  c2 = new ColorCircle(300, 40, 3.5, color(0, 0, 255));
}
 
void draw() {
 
  background(255);    //背景は白
 
  //c1インスタンスのクラスである、ColorCircleクラスのupdate()と
  //displayColor()メソッドを実行
  c1.update(); 
  c1.displayColor();
 
  c2.update(); 
  c2.displayColor();
}
 
void keyPressed() {
 
  if (key == CODED) {
    if (keyCode == UP) {  //上に動く
      c1.faster();
      c2.faster();
    } else if (keyCode == DOWN) {    //下に動く
      c1.slower();
      c2.slower();
    }
  }
}

完成したファイル【リスト5.3-i】 ダウンロード

もちろん、このサンプルを配列化することもできます。このことによって、たくさんの自律的なオブジェクトを作成することができます。

2016_09_30_3_50
図5.3-o

・【リスト5.3-j】フォルダ

・oop_circle_velocity_array.pde(実行ファイル – 新規)
・Circle.pde(クラスファイル – 再利用)
・ColorCircle.pde(クラスファイル – 再利用)

Circle.pdeとColorCircle.pdeは【リスト5.3-i】のサンプルと同じなので、省略します。

oop_circle_velocity_array.pde

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//ColorCircleクラスのインスタンスを100個宣言
ColorCircle[] c = new ColorCircle[100];
 
void setup() {
 
  size(400, 400);
  smooth();    //図形の輪郭をきれいに描画
  noStroke();
  fill(0);    //黒で描画
 
  for (int i = 0; i < c.length; i ++) {
 
    c[i] = new ColorCircle(i * 4, //y座標
                           4, //円のサイズ
                           random(0.01, 5.0), //スピードをランダムに決定
                           color((int)random(255), 100, 0));    //色
  }
}
 
void draw() {
 
  background(255);    //背景は白
 
  //c1インスタンスのクラスである、ColorCircleクラスのupdate()と
  //displayColor()メソッドを実行
  for (int i = 0; i < c.length; i ++) {
    c[i].update(); 
    c[i].displayColor();
  }
}
 
void keyPressed() {
  if (key == CODED) {
    if (keyCode == UP) {  //上に動く
 
      for (int i = 0; i < c.length; i ++) c[i].faster();
    } else if (keyCode == DOWN) {    //下に動く
 
      for (int i = 0; i < c.length; i ++) c[i].slower();
    }
  }
}

完成したファイル【リスト5.3-j】 ダウンロード

1 thought on “5.3 オブジェクト指向プログラミング2

  1. Pingback: Processing触ってみた | 水玉製作所

Comments are closed.