第20回 – class 3 メンバ変数


前回はclassの作り方と、インスタンス化の仕方について解説しました。
今回は、前回作ったsampleというなんの機能もないclassに、メンバ変数メンバメソッドを与えて、すこし実用的なclassにしてあげたいと思います。

メンバ変数?

メンバ変数というのは、そのclassのインスタンスが保持する変数の事です。

例えば、int型の変数ですと、int型の1つの値しか扱えません。
int型の配列も、数は沢山扱えますが、int型の値だけです。

もし四角形を描いて、それに名前をつけて、さらに好きな色で塗りたい、と思った時に、普通に考えれば以下の変数を用意しなければなりません。
int x(四角形の左上の位置)
int y(四角形の左上の位置)
int size(大きさ)
int addX(x方向に進む早さ)
int addY(y方向に進む早さ)
color fillCol(色)
color borderCol(外枠の色)
String name(名前)

しかし、そのプラグラムではもちろん他の形や他の機能も扱わなければなりませんし、そもそもこんなに沢山の変数の名前を考えたり覚えておいたり把握するのが大変です。同じ変数名は使えませんから、もし同じように円に名前をつけて塗る、という機能を追加しようとすると、倍の数の変数と変数名が必要になります。
頭のなかはごちゃごちゃですし、変数名は区別するためにどんどん長くなっていきます。
int ellipseX
int ellipseY
int ellipseSize
int ellipseAddX;
int ellipseAddY;
color ellipseFillCol
color ellipseBorderCol
String ellipseName;

classを使わずにやると、こんな感じです。

int x;
int y;
int size;
int addX;
int addY;
color fillCol;
color borderCol;
String name;
int ellipseX;
int ellipseY;
int ellipseSize;
int ellipseAddX;
int ellipseAddY;
color ellipseFillCol;
color ellipseBorderCol;
String ellipseName;

void setup(){
  
  size(800,800);
  x = 100;
  y = 100;
  addX = 2;
  addY = 1;
  size = 50;
  fillCol = color(255,0,0);
  borderCol = color(200,0,0);
  name = "SHIKAKUKEI";
  
  ellipseX = 50;
  ellipseY = 50;
  ellipseSize = 50;
  ellipseAddX = 1;
  ellipseAddY = 2;
  ellipseFillCol = color(0,255,0);
  ellipseBorderCol = color(0,200,0);
  ellipseName = "EN";
  
}


void draw(){
  
  background(0);
  
  fill(fillCol);
  stroke(borderCol);
  rect(x,y,size,size);
  x += addX;
  y += addY;
  
  fill(ellipseFillCol);
  stroke(ellipseBorderCol);
  ellipse(ellipseX, ellipseY, ellipseSize, ellipseSize);
  
  ellipseX += ellipseAddX ;
  ellipseY += ellipseAddY;
  
}

確かにこの方法でも、このくらいならなんとかならなくもないですが、これに何かしらの機能や動きを持たせると考えると、多分人間の頭では不可能…という感じになっていきます。あと図形の形が10個出てきたら、変数の数を5倍にしなければなりませんし、 +=などの演算がどこで何を行っているのかが把握できなくなっていきます。

そこで、classのメンバ変数としてこれらの値を四角形に名前をつけて色を塗るためのclassにまとめてあげれば、もう変数名等をそれぞれに覚えておく必要がなくなります。さらに、所属しているclassが違えば、同じ変数名を使用することが可能です。

class RectData {

  int x;
  int y;
  int size;
  int addX;
  int addY;
  color fillCol;
  color borderCol;
  String name;
}
class EllipseData {

  int x;
  int y;
  int addX;
  int addY;
  int size;
  color fillCol;
  color borderCol;
  String name;
}

こんな具合です。全く同じ変数名を使っていますが、classが違うので問題ありません。
使う時にはインスタンス化します。その時、コンストラクタをclassにもたせてあげると、変数を代入するのが楽になります。

class RectData {
  int x  = 0;;
  int y = 0;
  int size = 0;
  int addX = 0;
  int addY = 0;
  color fillCol = color(0,0,0);
  color borderCol = color(0,0,0);
  String name = "name";
  
  RectData(int _x, int _y, int _size) {
    x = _x;
    y = _y;
    size = _size;
  } 
}

RectData(int _x, int _y, int _size) { }この部分がコンストラクタと呼ばれる部分です。
コンストラクタを利用するには、class名と同じ名前をclassの { }の中に書いて、受け取りたい数の引数を()の中に書きます。
メソッドの時にやったのと同じように、引数の名前と型を指定してあげると、その名前で受け取った数を扱うことが出来るようになります。

コンストラクタは、classがインスタンス化される時に1度だけ呼ばれて、いくつかの引数を受け取ります。
そして、その受け取った引数をメンバ変数に渡します。
使用する場合には

RectData rData;

void setup(){
  size(800,800);
  
  rData = new RectData(100,100,50);
  
}
class RectData {
  int x  = 0;;
  int y = 0;
  int size = 0;
  int addX = 0;
  int addY = 0;
  color fillCol = color(0,0,0);
  color borderCol = color(0,0,0);
  String name = "name";
  
  RectData(int _x, int _y, int _size) {
  x = _x;
  y = _y;
  size = _size;
  } 
  
}

このようにします。
例ですと、100と100と50が、それぞれRectDataクラスの、xとyとsizeに代入されます。
さきほど setupの上に膨大にあったグローバルな変数が1つだけになっている点にも注目してください。
Ellipseを使っても2つですみます。

こうしておくことで、いくつかの代入を楽にする事ができます。もちろん、全てのメンバ変数に対してコンストラクタで初期値の代入を行っても問題ありません。ただ、コンストラクタが長すぎると、インスタンス化する時にその値と順番を毎回確認しなければならなくなってしまったり、渡すべき値を間違えてしまったりと問題が起こりやすいのでおすすめはしません。
(そういう場合にはBuilderパターンなどを使うのですが、その辺りはもう少し先の話です)

そして、このメンバ変数には
インスタンス名.変数名
でアクセス出来ます。
例えば、上の例だとこんな感じ。

RectData rData = new RectData(100,100,50);

rect(rData.x,rData.y,rData.size,rData.size);

しかし、実はこんな風にしなくても、もっと簡単にこのclassに持たせた変数を使って、図形を描く、移動するなどの振る舞いを実装する事が出来ます。
メンバメソッドという機能を利用するのですが、それはまた次回!