ということで第三回目はTemplate Methodです。
大枠の処理はスーパークラスで決めて細かいところはサブクラスに任せるってパターンですね。ストーリー的に言うと、頑固者の靴職人が、弟子に木型を渡して仕事をさせてるみたいな感じかな。
このパターンだとインターフェースを使用する意味がよくわかります。ということで早速コーディング。出てくる登場人物は三人です。
・AbstractDisplay.as(職人の親方です。displayメソッドを実装してます。)
・CharDisplay.as(弟子1です。)
・StringDisplay.as(弟子2です。)
・Main.as(お客さん。すなわち依頼主です。)
それではソースをみてきましょう。
最初につくったAbstractDisplay.asはこんな感じでした。参考書の通りに書いてみたパターン。
// AbstractDisplay.as(誤)
interface AbstractDisplay{
function open():String;
function print():String;
function close():String;
function display():String{
var tmp = open();
for(var i:Number = 0 ; i < 5 ; i++){
tmp = tmp+print();
}
tmp = tmp+close();
return tmp;
}
}
で、ここで問題発覚。ActionScript2.0のinterface内では、メソッドの宣言しかできなくて、実際にメソッドを実装しようとするとエラーが出ちゃいます。そもそも、javaで言うところのfinalキーワードが無いし。ただ、予約語として登録されているみたいなので、将来のバージョンでは実装されるのかな。
ということで、よくわかんなかったので、空のメソッドを用意する普通のClassを書いてみました。こういうのでいいのかな。よくないよな。
// AbstractDisplay.as
// AS2.0でインターフェースを使うと、メソッドの実装ができない。
// 普通のクラスを用意して後からオーバーライドするところは
// 空にしといてみた。
class AbstractDisplay{
function open():String{return "";};
function print():String{return "";};
function close():String{return "";};
function display():String{
var tmp = open();
for(var i:Number = 0 ; i < 5 ; i++){
tmp = tmp+print();
}
tmp = tmp+close();
return tmp;
}
}
やっぱり、return文のところが気持ち悪いや。
で、次が弟子1のCharDisplay.asです。頑固オヤジの親方の作った木型を元に実際の作業を行ってます。
// CharDisplay.as
class CharDisplay extends AbstractDisplay{
private var char:String;
function CharDisplay(s:String){
char = s;
}
function open():String{
return "<<";
}
function print():String{
return char;
}
function close():String{
return ">>";
}
}
さらに次が弟子2のStringDisplay.as。ほぼ一緒なんだけど、こちらは文をリピートする感じ。どちらの弟子もdisplayメソッドは実装されていなく、これは最終的にお客様に出す仕事なので親方が受け持ってるような感じ。
最後にMain.as
//Main.as
class Main{
// メインクラス
function Main(path :MovieClip ) {
var d1 = new CharDisplay("H");
var d2 = new StringDisplay("Hello World");
var d3 = new StringDisplay("こんにちは!");
var tmp = d1.display();
tmp = tmp +"¥n"+ d2.display();
tmp = tmp +"¥n"+ d3.display();
path.createTextField("tf", 1, 5, 5, 190, 190);
path.tf.border = true;
path.tf.multiline= true;
path.tf.wordWrap= true;
path.tf.text = tmp;
}
static function main() {
var t :Main= new Main(_root);
}
}
特に説明するところはないかな。
いつもの通りmtascから
mtasc -swf templateMethod.swf -main Main.as -header 200:200:30
とすると。ほら動いたでしょ。
Template Methodは似たようなクラスがいっぱいできちゃいそうな時に使うといいみたい。そのときのスパークラスにどれくらい仕事させるかのさじ加減が腕の見せ所なのかな。サブクラスで書く処理が重複しすないように、かつ自由度が減らないように。まさにサブクラスを「抽象」するクラス。すなわち「抽象」クラスなのか。なるほど。って文だけみるとなに言ってんのという感じですが。
まあ、だいぶ慣れて来たみたい。
考え方のポイントがだいぶつかめるようになってきた。
ということで次回。