導入
前項の「クラス」を引き継ぐ「継承」という手法を使い,自分で定義したクラスを拡張し,複数存在させる.
継承(拡張)の概念
Ballクラスは前項と同じであるが,もう一つExtendedBall
というクラスを指定している.クラスを定義する時にextends
(拡張する)というキーワードの後にBallクラスの名前を指定している.
継承したExtendedBallでは,Ballクラスのメンバ変数,メンバ関数が「宣言しなくても」使えるようになる.さらにメンバ変数やメンバを加えることができる.
継承元であるBallクラスのことを「親クラス」もしくは「スーパークラス」と呼び,継承先のExtendedBallクラスのことを「子クラス」もしくは「サブクラス」と呼ぶ.
コンストラクタの取り扱い
子クラスのコンストラクタの一番最初では必ずsuper();
を書く.これは「スーパークラスのコンストラクタ」という意味である.
もし子クラスの中でコンストラクタを宣言しない場合,自動的に親クラスのコンストラクタが実行される.
メンバ関数のオーバーライド(Override)
親クラスに含まれるメンバ変数/メンバ関数は,子クラス内では宣言せずにそのまま使うことができるが,関数そのものを拡張したい場合が殆どである.
コード例ではBallクラスを継承したExtendedBallクラスでは,色情報を保持する変数rColor, gColor, bColor
と色の増減情報rDirection, gDirection, bDrection
が含まれている.ExtendedBallクラスのupdatePosition()
メンバ関数内では,今までやってきたようにこれらの情報の増減も同時に行いたい.そこでオーバーライド「関数の上書き」を行う.関数定義をもう一度書けば良い.
オーバーライドを行う場合,その関数を定義し直す頭に@Override
キーワードをつける必要がある.
(「オーバーロード」という概念もあるが,オーバーライドとオーバーロードは別のものなので注意すること.)
コード
//ExtendsClass_Ball.pde
Ball ballArray[] = new Ball[10];
ExtendedBall extendedBallArray[] = new ExtendedBall[10];
void setup(){
size(640, 480);
colorMode(RGB, 255);
background(255, 255, 255);
frameRate(10);
for(int i=0; i<10; i++){
ballArray[i] = new Ball();
extendedBallArray[i] = new ExtendedBall();
}
}
void draw(){
drawRefreshRect(255, 255, 255, 60);
for(int i=0; i<10; i++){
ballArray[i].drawBall();
extendedBallArray[i].drawBall();
}
for(int i=0; i<10; i++){
ballArray[i].updatePosition();
extendedBallArray[i].updatePosition();
}
}
void drawRefreshRect(int r, int g, int b, int alpha){
noStroke();
fill(r, g, b, alpha);
rect(0, 0, width, height);
}
//Ball.pde 前項と全く同じものである.
class Ball{
int x;
int y;
int ballWidth = 20;
int ballHeight = 20;
int xDirection;
int xSpeed;
Ball(){
x = (int)random(width);
y = (int)random(height);
if(random(2) < 1){
xDirection = 1;
}
else{
xDirection = -1;
}
xSpeed = (int)random(5) + 1;
}
void updatePosition(){
x += xSpeed * xDirection;
if(x > width){
xDirection = -1;
}
else if(x < 0){
xDirection = 1;
}
}
void drawBall(){
fill(30, 30, 30);
ellipse(x, y, ballWidth, ballHeight);
}
}
//ExtendedBall.pde
//Ballクラスを継承(し拡張)したもの.
class ExtendedBall extends Ball{
//Extends: Generate Child Class from Parent Class
//extendsキーワードで,既にある(同じプロジェクトの中に入っている)クラスを「継承」
//継承元のクラス(親クラス)にはない,
//継承先(このクラスのこと,子クラス)のみの変数を追加する
int rColor;
int gColor;
int bColor;
int rDirection;
int gDirection;
int bDirection;
ExtendedBall(){
//Execute Parent Class Constructor
//親クラスのコンストラクタを実行するsuper();
super();
//その後に子クラスのコンストラクタ処理を記述していく
rColor = (int)random(155) + 100;
gColor = (int)random(155) + 100;
bColor = (int)random(155) + 100;
if((int)random(100) > 50){
rDirection = 5;
gDirection = 5;
bDirection = 5;
}
else{
rDirection = -5;
gDirection = -5;
bDirection = -5;
}
}
@Override
void updatePosition(){
//@Override Keyword:
//Writing New Definition of Function of Parent Class
//@Overrideキーワード
//親クラスに定義されている関数の定義を上書きする(同名の関数を作る)時に使うキーワード
//なくても動作はするが一応ちゃんと書いておくこと.
//Overrideした時点で親クラスの同名関数は,継承したこのクラスでは空になっているので,
//定義していく
//Overrideしなければ,親クラスの関数がそのまま使われる
//必要な関数のみ上書き拡張すれば良い
x += xSpeed * xDirection;
if(x > width){
xDirection = -1;
}
else if(x < 0){
xDirection = 1;
}
//Update RGB
rColor += rDirection;
gColor += gDirection;
bColor += bDirection;
//Update rDirection
if(rColor > 255){
rDirection = -5;
}
else if(rColor < 100){
rDirection = 5;
}
//Update gDirection
if(gColor > 255){
gDirection = -5;
}
else if(gColor < 100){
gDirection = 5;
}
//Update bDirection
if(bColor > 255){
bDirection = -5;
}
else if(bColor < 100){
bDirection = 5;
}
}
@Override
void drawBall(){
//同じくOverrideする
fill(rColor, gColor, bColor);
ellipse(x, y, ballWidth, ballHeight);
}
}