prototype.js の Class 拡張試案 (Main, Singleton etc.)
Update [20060301]: id:reinyannyan:20051118:p1 の末尾に修正点を追記しましたのでご覧下さい。
id:reinyannyan:20051015:1129388215 において、prototype.js の Object.prototype 汚染の問題を紹介させて頂きました。
その文脈の中で、(コーディングの便のため)クラス定義の場合に限り、従来の extend メソッドが使えないか、ということを考えました。
今回はそのアイディアを押し広げて、全面的に Class オブジェクトを書き換えてみたものをお見せしたいと思います。
abstract と concrete
Class::create の拡張です。
var Class = { abstract: function () { return function () { Object.extend(this, Class.Methods); }; }, concrete: function () { return function () { Object.extend(this, Class.Methods); this.initialize.apply(this, arguments); }; }, ... }; Class.create = Class.concrete;
これまで空関数を使用して定義していた抽象クラスを Class.abstract() として定義できるようにします。この関係で、create にあたるものを、意味論的一貫性のため、concrete として定義しております。
Class.Methods の中身はこのようなものです。
Class.Methods = { clone: function () { return Object.clone(this); }, extend: function (object) { return Object.extend(this, object); } };
Object::clone については id:reinyannyan:20051017:1129555088 を参照してください。
Main
C 等の main にあたる関数をクラスとして定義するためのものです(ブラウザで実行されるスクリプトを想定しています)。
var Class = ... main: function () { return function () { window.onload = this.main.bind(this); window.onunload = this.unmain.bind(this); }; }, ...
一般クラスの initialize に代わり、main と unmain メソッドの定義を義務付けます。
利用サンプル:
var Main = Class.main(); Main.prototype = { main: function () { // main code }, unmain: function () { // cleanup code here } }; new Main; // program starts
new するとプログラム開始です。ページのロードと同時に main が実行されます。unmain は、window の unload 時に実行すべきクリーンアップ・コードです。ネーミングはあまり一般的ではないと思いますが、load と unload との対称ということで。
unmain は要らないという場合は、if を付けるか、
window.onunload = (this.unmain || Prototype.emptyFunction).bind(this);
のようにしても良いかと思います。
Singleton
id:reinyannyan:20051015:1129356763 の改良版(?)です。
var Class = ... singleton: function () { return Object.extend({ instance: null }, Class.Methods); }
利用サンプル:
var Singleton = Class.singleton().extend( { getInstance: function () { if (!this.instance) { // constructor var singleton = Class.create(); singleton.prototype = { ... }; this.instance = new singleton; } return this.instance; } });
メソッドを作るほどでもないような気もしますね…。まぁおまけということで。