何かがたくさん出てくるプログラム
オブジェクト指向プログラミング (Object-Oriented Programming; OOP)

新登場する言葉

例:丸がたくさん?

丸がたくさん振ってくるプログラムを書いてみましょう。「たくさん」と言えば「配列」でした。これまでに学んだことを使うとたとえばこんな感じに書けると思います。 ちょっと雪景色っぽく見えるように丸の初期配置や大きさをランダムに決定しています。

float[] x;
float[] y;
float[] size;

void setup(){
  x = new float[20];
  y = new float[20];
  size = new float[20];
  for(int i = 0; i < x.length; i++){
    x[i] = random(width);
    y[i] = random(height);
    size[i] = random(10);
  }
}

void draw(){
  background(0);
  fill(255);
  for(int i = 0; i < x.length; i++){
    y[i] = (y[i] + 2) % height;
    ellipse(x[i], y[i], size[i], size[i]);
  }  
}

書けたのはいいのですが、「丸がたくさん」ではなく、「丸のx座標がたくさん、y座標もたくさん、大きさもたくさん」という感じになっていて少しわかりにくいような気がします。 「丸」を表す型があればもっと素直に Circle[] circles と書けるのですが…。

クラスとオブジェクト

ほしい型がないなら自分で作っちゃおうということで登場するのが「クラス」です。クラスを使うと、複数の変数をひとまとめにした新しい型を定義することができます。 たとえば以下では float 型の変数 x, y, size を持つクラス Circle を定義しています。

class Circle {
  float x;
  float y;
  float size;
}
文法:クラスの定義
class クラス名 {
   // クラスの中身(メンバーと呼びます)
}

これで3つの変数が1セットになった新しい型ができました。ここでの x, y, size のように、クラスに属している変数のことをそのクラスの「メンバー変数」と呼びます。

オブジェクトの作成と利用

クラスそのものはデータではなく、データの設計図のようなものに過ぎません。設計図であるクラスから具体的なデータを作成して利用します。作成される個々のデータのことを「オブジェクト」と呼びます。 作成したオブジェクトは他のデータと同じように変数や配列にしまっておきます。実際に、上で作成した Circle クラスのオブジェクトを作成・利用してみましょう。

Circle c; // 変数の宣言

c = new Circle(); // オブジェクトの作成
c.x = random(width);  // c の x
c.y = random(height); // c の y
c.size = random(10);  // c の size

c.y = (c.y + 2) % height;
ellipse(c.x, c.y, c.size, c.size);
文法:オブジェクトの作成には配列と同じように new を使います。
変数 = new クラス名();
文法:オブジェクトのメンバー変数を利用するには . (ドット) を使います。
オブジェクト.メンバー変数

最初の雪景色っぽいプログラムを Circle クラスを使って書き直してみると以下のようになります。

Circle[] circles;

void setup(){
  circles = new Circle[20];
  for(int i = 0; i < circles.length; i++){
    circles[i] = new Circle();
    circles[i].x = random(width);
    circles[i].y = random(height);
    circles[i].size = random(10);
  }
}

void draw(){
  background(0);
  fill(255);
  for(int i = 0; i < circles.length; i++){
    Circle c = circles[i];
    c.y = (c.y + 2) % height;
    ellipse(c.x, c.y, c.size, c.size);
  }  
}

class Circle{
  float x;
  float y;
  float size;
}

応用編:ボタン

応用編として、前回までに学んだマウス操作に反応するプログラムの書き方を応用して、押された回数を数えてくれるボタンが表示されるプログラムを作成してみましょう。 まずは、クラスを使わない書き方で行きます。

boolean isPressed;
int count;
float cx, cy; // (cx, cy) = center of the button
float w, h;   // width and height of the button

void setup() {
  size(200, 200);
  rectMode(CENTER);
  textAlign(CENTER);
  setupButton(width * 0.5, height * 0.5);
}

void draw() {
  background(255);
  drawButton();
}

void mousePressed() {
  checkButtonPress();
}

void mouseReleased() {
  checkButtonRelease();
}

void setupButton(float x, float y) {
  isPressed = false;
  count = 0;
  cx = x;
  cy = y;
  w = 100;
  h = 40;
}

void drawButton() {
  if (isPressed) {
    fill(128);
  } else if (isOnTheButton(mouseX, mouseY)) { // Mouse is hovering on the button
    fill(192);
  } else {
    fill(160);
  }
  rect(cx, cy, w, h);
  fill(0);
  text("Count: " + count, cx, cy);
}

void checkButtonPress(){
  if (isOnTheButton(mouseX, mouseY)) isPressed = true;
}

void checkButtonRelease(){
  if(isPressed && isOnTheButton(mouseX, mouseY)) count++;
  isPressed = false;
}

boolean isOnTheButton(int x, int y) {
  return abs(cx - x) < w / 2 && abs(cy - y) < h;
}

ボタンを複数にする…?

上記のプログラムで1つのボタンを作ることができました。それを元に複数のボタンが登場するプログラムを作ってみましょう。

boolean[] isPressed;
int[] count;
float[] cx, cy;
float[] w, h;

となるのはかなり大変そうなので、丸のときのように Button[] bs と書けるように Button クラスを作りましょう。

class Button {
  boolean isPressed;
  int count;
  float cx, cy;
  float w, h;
}

実は、クラスには変数だけでなく関数も含めることができます。ボタンに関係する関数は同じクラスに入れてしまうのが自然な発想でしょう。

class Button {
  boolean isPressed;
  int count;
  float cx, cy;
  float w, h;

  void setupButton(float x, float y) {
    isPressed = false;
    count = 0;
    cx = x;
    cy = y;
    w = 100;
    h = 40;
  }

  void drawButton() {
    if (isPressed) {
      fill(128);
    } else if (isOnTheButton(mouseX, mouseY)) { // Mouse is hovering on the button
      fill(192);
    } else {
      fill(160);
    }
    rect(cx, cy, w, h);
    fill(0);
    text("Count: " + count, cx, cy);
  }

  void checkButtonPress() {
    if (isOnTheButton(mouseX, mouseY)) isPressed = true;
  }

  void checkButtonRelease() {
    if (isPressed && isOnTheButton(mouseX, mouseY)) count++;
    isPressed = false;
  }

  boolean isOnTheButton(int x, int y) {
    return abs(cx - x) < w / 2 && abs(cy - y) < h;
  }
}

クラスに属している関数のことを「メンバー関数」と呼びます。

タブの作成

なかなかボリューム感のあるクラスになりました。クラスを作成するなどしてプログラムが長くなってきたときには複数のファイル(タブ)に分けるのがオススメです。

  1. エディタ上部のタブの右側にある小さな矢印アイコンをクリックすると出てくるメニューから New Tab を実行
    あるいはキーボードから Ctrl + Shift + N
  2. 作成するタブの名前を入力して OK (作成するクラスの名前にしておくとわかりやすい)
  3. 新しいタブに Button クラスのプログラムを移す

作成した Button クラスを利用して、先ほどのプログラムを書き直すと以下のようになります。

Button b;

void setup() {
  size(200, 200);
  rectMode(CENTER);
  textAlign(CENTER);
  b = new Button();
  b.setupButton(width * 0.5, height * 0.5);
}

void draw() {
  background(255);
  b.drawButton();
}

void mousePressed() {
  b.checkButtonPress();
}

void mouseReleased() {
  b.checkButtonRelease();
}

ボタンに関する詳細を Button クラスの中に入れてしまった分、プログラムがすっきりしました。

複数のボタンを表示する

あとは…できますよね?

Button[] bs;

void setup() {
  size(200, 200);
  rectMode(CENTER);
  textAlign(CENTER);
  bs = new Button[3];
  for(int i = 0; i < bs.length; i++){
    bs[i] = new Button();
    bs[i].setupButton(width * 0.5, 40 + i * 60);
  }
}

void draw() {
  background(255);
  for(int i = 0; i < bs.length; i++){
    bs[i].drawButton();
  }
}

void mousePressed() {
  for(int i = 0; i < bs.length; i++){
    bs[i].checkButtonPress();
  }
}

void mouseReleased() {
  for(int i = 0; i < bs.length; i++){
    bs[i].checkButtonRelease();
  }
}

コンストラクタ

setupButton 関数のようなオブジェクト作成時の初期化処理は、「コンストラクタ」と呼ばれる特別なメンバー関数を作成することで new によるオブジェクト作成とまとめることができます。 setupButton 関数を以下のように書き換えてコンストラクタを作成してみましょう。

Button(float x, float y) {
  isPressed = false;
  count = 0;
  cx = x;
  cy = y;
  w = 100;
  h = 40;
}
文法:コンストラクタの定義
クラス名(引数) {
  // 初期化処理
}

クラス名と同名の関数を作るとコンストラクタになります。返り値の型指定 void が不要になることに注意しましょう。

このようにコンストラクタを作成しておくと以下のように1行でオブジェクトの作成とメンバー変数の初期化を行うことができます。

bs[i] = new Button(width * 0.5, 40 + i * 60);

今回のようにクラスやオブジェクトを利用するプログラミングを「オブジェクト指向プログラミング」と呼びます。おつかれさまでした! Happy Programming!!!

© 2015- Takeshi NISHIDA