今回はクラスの「継承」の基本的な仕組みと,具体的な継承の方法をご紹介します。継承の仕組みをうまく利用すると,既存のクラスを拡張した便利なクラスを作成できたり,「同じグループのクラス」として利用するのが容易になります(図1)。
図1: 継承のイメージ(クリックするとムービーを表示します)
extendsするのが「継承」
あるクラスを継承するということは,「そのクラスのできることは私もすべてできます」という証明書のようなものです。さらにそれに加えて,独自にできることが増えていくわけですね。同じクラスを継承するクラスは,どのクラスも「最低限,継承したクラスのできることはできる」グループとして扱うことができます。ActionScript2.0で,あるクラスを「継承」したクラスを作成するには,「extendsキーワード」を使用します。「extends」は日本語にそのまま訳すと「伸ばす」「拡張する」というような意味になります。つまり,あるクラスを「拡張した」言い換えると,「付け足した」クラスを作成するというわけですね(図2)。
図2: extendsするということ
その結果,当然ですが新しく作成したクラスでは,継承元となるクラスの持つプロパティやメソッドはすべて使用できます。それに加え,新たに付け足した部分の機能を持つクラスとなるわけです。いつも使っていたテンプレート定規に,extends部分のアタッチメントを取り付けて使えるようにした仕組みと言えます。
このように,クラスを「継承する」「extendsする」というのは,「あることができるクラスをベースに,それを拡張したクラスを作成する」という作業をしているわけです。
実際に作ってみよう
では,実際にActionScript2.0でクラスを作成してみましょう。まずは「x」と「y」の二つのプロパティを持ち,引数として受け取ったインスタンスを,x,yプロパティの値の場所へ配置する「pointMC2D」メソッドを一つだけもつクラス,「Point2Dクラス」があるとします(リスト1)。簡単な縦・横の位置情報を格納するためのクラスです(*1)。リスト1: Point2Dクラスのコード
class Point2D{ var x:Number; var y:Number; function pointMC2D(_mc:MovieClip):Void{ _mc._x = x; _mc._y = y; } }
このPoint2Dクラスに,疑似的なz軸方向の考え方を加えた「Point3Dクラス」を作成してみましょう。Point3Dクラスでは,Point2Dクラスのx,yプロパティに加え,「zプロパティ」を加えてみます。そして,zプロパティの値を使って引数として受け取ったインスタンスを,x,yプロパティの値に場所に,zプロパティの拡大率で配置する「pointMC3D」メソッドを追加したいと思います。
つまり,Point3Dクラスは,表1のような三つのプロパティと二つのメソッドを持つクラスとしたいわけですね。
プロパティ,メソッド | 説明 |
---|---|
xプロパティ | 横座標の位置を管理 |
yプロパティ | 縦座標の位置を管理 |
zプロパティ | 奥行き座標の位置を管理(拡大率を管理) |
pointMC2Dメソッド | x,yの位置にインスタンスを配置 |
pointMC3Dメソッド | x,y,zの位置にインスタンスを配置 |
このうち,x,yの両プロパティ,pointMC2Dメソッドは,Point2Dクラスのものと全く同じわけですので,ここはPoint2Dクラスを「継承」してPoint3Dクラスを作成してみたいと思います。
「継承」を行うには,
class 作成するクラス名 extends 継承するクラス名{ //定義 }
というようにコードを記述します。また,プロパティやメソッドの記述に関しては,新たに付け足したいもののみを作成するクラス側に記述します。今回のPoint3Dクラスのケースですと,次のようなコードになります(リスト2)。x,yプロパティ,pointMC2Dメソッドの記述は必要ありません。付け足したいものだけを書けばOKです。
リスト2: Point3Dクラスのコード
class Point3D extends Point2D { var z:Number; function pointMC3D(_mc:MovieClip):Void { _mc._x = x; _mc._y = y; _mc._xscale = z; _mc._yscale = z; } }
では,この二つのクラスを使って,実際にインスタンスを配置してみましょう。図3のように,タイムラインに配置すると,ステージの右方向へと移動するムービークリップ・シンボル「SpaceShip」を準備します。また,SpaceShipのインスタンスは,移動の際,拡大率(_xscaleプロパティの値)に応じて速度が調整されるようなコードが記述してあります(*2)。
図3: 今回利用するシンボルとその動き(クリックするとムービーを表示します)
このシンボル「SpaceShip」を,Point2Dクラスをつかって,ステージにランダムに10個配置してみます。コードは,次のようになります。
import Point2D; //初期表示の範囲を設定 var MAX_X:Number = 320; var MAX_Y:Number = 200; //10個のPoint2Dクラスを生成 var pointList:Array = new Array(); var _p:Point2D; for(var i:Number = 0;i<10;i++){ _p = new Point2D(); _p.x = Math.random()*MAX_X; _p.y = Math.random()*MAX_Y; pointList.push(_p); } //pointMC2Dメソッドで「SpaceShip」のインスタンスを生成・配置 var _mc:MovieClip; for(i=0;i<pointList.length;i++){ _mc = _root.attachMovie("SpaceShip","_sp" + i,i); pointList[i].pointMC2D(_mc); }
実行結果は図4のようになります。10個のインスタンスが,Point2Dクラスの情報を使ってランダムな場所に配置されていることが確認できますね。
図4: Point2Dクラスでインスタンスを配置(クリックするとムービーを表示します)
では,お次はPoint3Dクラスを使って同じようにインスタンスを配置してみましょう。クラスファイルには,zプロパティとpointMC3Dメソッドを書いた以外は,Point2Dクラスを「extend」していただけですが,はたしてきちんと値を持っているでしょうか。
import Point3D; //初期座標の範囲を設定 var MAX_X:Number = 320; var MAX_Y:Number = 200; //10個のPoint3Dクラスを生成 var pointList:Array = new Array(); for(var i:Number = 0;i<10;i++){ var _p:Point3D = new Point3D(); _p.x = Math.random()*MAX_X; _p.y = Math.random()*MAX_Y; _p.z = Math.random()*60 + 40; //最低限40 pointList.push(_p); } //Point3Dクラス座標に「SpaceShip」のインスタンスを生成 var _mc:MovieClip; //深度管理対策のために,zの値が小さい順に並べ替え pointList.sortOn("z"); //pointMC3Dメソッドで「SpaceShip」のインスタンスを生成・配置 for(i=0;i<pointList.length;i++){ _mc = _root.attachMovie("SpaceShip","_sp" + i,i); pointList[i].pointMC3D(_mc); }
実行結果は,図5のようになります。Point3Dクラスを使用してPoint2Dクラスで定義したx,yの二つのプロパティ,さらにPoint3Dクラスで定義したzプロパティにpointMC3Dメソッドが使用できていることが確認できますね。
図5: Point3Dクラスでインスタンスを配置(クリックするとムービーを表示します)
Point3DクラスはPoint2Dクラスを継承していますので,そのままpointMC2Dメソッドを実行することもできます。
このように,extendsキーワードを使って,あるクラスを「継承」すると,そのクラスに用意されているプロパティやメソッドを引き継いだうえに,さらにプロパティやメソッドを「付け足し」をしたクラスを作成することができます。
今回は「継承」の仕組みの基本的な所をご紹介しました。でも,継承の本当の便利なところは,既存のクラスにツギハギして新しいクラスを作成できるという「再利用」の観点とは,別の所にあります。
次回は,この「継承」の仕組みに加えて「多態性」「オーバーライド」という考え方と仕組みを利用したコードの作成方法をご紹介します。お楽しみに。