カレーうどんが好きです。今日のお昼はカレーうどんでした。正宗です。
今日はJavascriptでクラス開発をしてみたいと思います。
冒頭のカレーうどんは関係ないですね。何かいわなきゃと思ってつい好物を出してみました。
ご存じのとおり、Actionscriptはもともとバージョン1の頃はJavascriptとほぼ同じ言語であり、つまりAS1の頃のクラス開発がそのまま使える形となっています。
そこでJavascriptでクラスを作ったりするときに「あれ?ASだとこうやるやり方、JSだとどうやるんだっけ」ってのを減らせるように、完全に個人的な備忘録を作ってみました。自己流なうえにオレオレ規約ばっかりで恥ずかしい限りですがせっかく作って公開したのでなんらかのお役にたてばうれしいです。
Javascriptでのクラスの作り方は本当にたくさんの方法がありますが、その中で僕が一番馴染んでいる書き方だけを勝手に選んでのせています。
さっきふと思い立ってやった方法をそのままばんばんのせている感じです。
あと、JSとの類似性を浮き上がらせるためにASにはあえて型を宣言しないで書いています。
ASやJSの綺麗なコードの書き方ではなく、あくまでもASに似せたやり方でJSを書いていく方法を探った記事ですのでご了承ください。
あと、技術書でも何でもなくあくまで個人の備忘録ですので恥ずかしながら盛大に間違えている箇所がたくさんあるかと思います。その場合間違いは常に正していきたいのでご指摘頂けると大変嬉しいです。
ほんと僕のブログ間違いもおおいんで前置きも長々となってしまってすいません。
同じ処理を最初にAS3、次にJSの順番で書いてみたいと思います。
クラスを使ってみる
クラスを使う方法はまさに全く同じです。
actionscript3
//インスタンスメンバを使う場合。 var d = new Date(); trace(d.getTime()); //クラスメンバを使う場合。 trace(Math.random());
javascript
//インスタンスメンバを使う場合。 var d = new Date(); console.log(d.getTime()); //クラスメンバを使う場合。 console.log(Math.random());
つまり作り方の違いさえうまく吸収できれば、クラスを使うぶんにおいてはほぼ全くといっていいほど同じように使えるようになるってことではあーりませんか。
こりゃいいや、さっそく作り方をまとめてみよう。
クラスを作ってみる
AS3のほうは意図的にpackageブロックを書いていません。
actionscript3
public class Human { public function Human() {} }
javascript
/** * @constructor */ function Human(){};
Javascriptではfunction宣言するだけでクラスが作れます。この部分がそのままコンストラクターになります。
作ったクラスは先ほどみたいにASでもJSでも全く同じように
var John = new Human();
こういうふうに使えるようになります。
プライベートプロパティ、プライベートメソッドを作ってみる
JSでは言語としてprivateをサポートしてないっぽい?
言語がサポートしていない以上、なんとかして隠匿化するコードを書いた方が良いのかもしれませんが、個人的にはオリジナルで処理を組むよりは規約を作ってこういったチェックツールに頼る方が好みなので、JSのほうはGoogleのコーディング規約を参考にこうしてみました。
まあClosure Linterまだ使ったことないですが。
actionscript3
public class Human { public function Human() {} private var himitsu_ = 'わりと最近うんこをもらした'; private function think_() { trace('(´-`).。oO(蛇口からビールが出ればいいのになあ…。'); } }
javascript
/** * @constructor */ function Human(){ /** @private */ this.himitsu_ = 'わりと最近うんこをもらした'; /** @private */ this.think_ = function() { console.log('(´-`).。oO(蛇口からビールが出ればいいのになあ…。'); }; };
JSのほうは、コンストラクタ内で宣言することで「これはプライベートな空間なんですよ」と(自分が)強く思い込むことにしました。
2012/01/29 追記
コンストラクタ内でvar で宣言しておいて、getter/setterで操作するってやり方を今知りました。うーん、それ使うかどうしようか迷う…。
2012/01/29 さらに追記
さっそく@taikikenさんからpublic/privateをわける方法を教えて頂きました。
ツイッター
JavaScriptでOOP – Classみたいなのにprivateな関数と変数 | イナヅマtvログ
コンストラクタ内でvarでプライベート宣言しておいた上で、mainというfunctionもprivateで保持しつつそこのprototypeにpublicな変数と関数を入れておいてreturnするというやり方ですね(僕が言葉にするとかえってわかりにくいですが教えて頂いたコードはすごい明快です)。プロトタイプベースのクラス、奥が深い!
パブリックプロパティ、パブリックメソッドを作ってみる
JSがprivateをサポートしていない(未確認)以上、publicもファブリックもあったもんじゃない(最近IKEAに行きました)のですが、JSのほうではprototypeに宣言することで「これはパブリックな空間にあるんですよ」と(自分が)強く思い込むことにしました。
actionscript3
public class Human { public var syumi = 'プリクラ集め、水に向かって綺麗な言葉を言い続けること'; public function work() { trace('|^o^|<ひきこもりぎみなのでそとをあるくのはにがてです'); } }
javascript
/** * @constructor */ function Human(){}; /** @public */ Human.prototype.syumi = 'プリクラ集め、水に向かって綺麗な言葉を言い続けること'; /** @public */ Human.prototype.work = function() { console.log('|^o^|<ひきこもりぎみなのでそとをあるくのはにがてです'); };
スタティックなプロパティやメソッドを作ってみる
JSではクラス(正確にはFunctionオブジェクト?)に直接定義することでstaticになりました。
actionscript3
public class Human { public static function help() { trace('困ったときはお互い様。'); } }
javascript
/** * @constructor */ function Human(){}; Human.help = function() { console.log('困ったときはお互い様。'); };
助け合いの心は人が誰もが持っている心。美しいですね(美)
継承してみる
僕の作ったクラスがだいぶ人としても完成されてきた頃なので、ここらで継承して新たなクラスを作ってみたいと思います。
actionscript3
public class Hentai extends Human{ public function Hentai() {} public function zenra() { trace('╰⋃╯'); } }
javascript
/** * @constructor * @extends {Human} */ function Hentai() {}; Hentai.prototype = new Human(); Hentai.prototype.zenra = function() { console.log('╰⋃╯'); };
Javascriptでは新たなクラスのprototypeにスーパークラスをインスタンス化させると継承できました。
オーバーライドしてみる
JSはそのまま親クラスを上書きするだけとしています。
actionscript3
public class Hentai extends Human{ public override function work() { //super.work(); trace('三╰⋃╯'); } }
javascript
/** * @constructor * @extends {Human} */ function Hentai() {}; Hentai.prototype = new Human(); /** @override */ Hentai.prototype.work = function() { //this.constructor.prototype.work.call(this , arguments); console.log('三╰⋃╯'); };
インターフェースを使ってみる
JSではインターフェースもサポートされていないので、インターフェースに似たふるまいをするコードを書くか書かないか、書くとしたらどこまで書こうか、ここ一番悩んだんですが、結局コードとしては一切書かないことにしました。
だいたいこの辺の記事を参考に、規約で実現する方法を探っているところです。今のところコメントにinterfaceと書いてるだけですが。
actionscript3
public interface IBijin { function yasashii(); function iinioi(); } public interface IIsya { function care(); } public class Jyoi implements IBijin, IIsya{ public function Jyoi() {} public function yasashii() {} public function iinioi() {} public function care() {} }
javascript
/** * @interface */ function IBijin() {}; IBijin.prototype.yasashii = function() {}; IBijin.prototype.iinioi = function() {}; /** * @interface */ function IIsya() {}; IIsya.prototype.care = function() {}; /** * @constructor * @implements {IBijin, IIsya} */ function Jyoi() {}; Jyoi.prototype.yasashii = function() {}; Jyoi.prototype.iinioi = function() {}; Jyoi.prototype.care = function() {};
こんな感じでしょうか?コードがなんかだいぶ投げやりになってきたなあ。
さいごに
僕がまとめた限りではまあだいたいこんなものではないでしょうか。
無理矢理にしてまでJSをASのクラスライクに書いていく必要はないと思いますが、わりかし自然にASっぽく書くことも出来なくはなさそうな感じはします。
今話題のArctic.jsやenchant.jsなど(ふたつとも僕はまだ残念ながら使えていないんですが)のようにASライクに書けるJSのライブラリも増えてきましたし、とりあえず横断的に開発してみたくてまとめてみました。
ASもそうですがJavascriptも独学の完全自己流なので本当は晒せるほどは自信がないですが、何かしら役に立てばなによりです。
「Actionscript3erが覚えるJavascriptでのクラス開発まとめ」への4件のフィードバック