classjs Wiki

classjs のWikiページへようこそ。

Class.js の機能

概要

 Class.jsは、JavaScriptのオブジェクト指向を強化するモジュールです。

 プロトタイプ・ベースの継承、インターフェース、仮想メンバー、抽象メンバー、クラスメンバー、プライベートメンバー、安全なスーパークラスへのアクセス、内部クラスなど、オブジェクト指向言語がサポートする機能の重要なもののいくつかをサポートしています。

開発の経緯

 Javascriptには、十分に機能する「オブジェクト指向」が実装されていません。

 現在のJavaScriptのオブジェクト指向的な機能は、既存の仕様の上に、後から追加する形で導入されているため、「とって付けた」感が否めない不完全なものにとどめられています。

 とくに、クラスという概念がなく、これを関数の拡張とプロトタイプの実装で代用したり、データのアクセス制御(public, protected, private)や、仮想メンバー、抽象メンバーがサポートのサポートがないことで、本来のオブジェクト指向の果実は、その大半が欠落しているといわざるをえません(ここで言う『メンバー』とは、オブジェクトのメソッドとプロパティの総称です)。

 また、スーパークラスへのアクセスにも、単に他クラスのプロトタイプを参照する(実際のスーパークラスかどうかは関係なく)だけにとどまっているため、『継承』の魅力は損なわれ、新たなバグの混入のリスクと背中合わせの状態に陥っています。

 さらに、Javaにおける多重継承の別解ともいえるインターフェースもないので、オブジェクトの多態性を利用した安全なコーディングも保証されません。

 この他、抽象クラスによる、メソッドやプロパティの未定義の検出、仮想メンバーによるオーバーライドの制御、クラスメンバー定義といった、一般のオブジェクト指向では当たり前に利用されているものすら存在しません(コードを駆使して似たようなことはできますが、そのコード自体が可読性を著しく崩壊させるという犠牲との取引になってしまいます)。

 そもそも、上記に挙げた(一部でありますが)オブジェクト指向言語の標準機能は、とくに、大規模なアプリケーションを構築する上では、余分な条件分岐のコードを減らし、未定義値へのアクセスや未定義メソッドの呼び出しという単純ミスを回避するなど、きわめて効果的なものばかりです。

 「Class.js」は、これらの機能を盛り込むと同時に、コードの表現そのものもシンプルにし、パフォーマンスの向上と、コーディング・デバッグ作業の単純化を目指した開発環境を提供するものです。

 なお、Class.jsはNode.jsのモジュールにも利用できます。

主な機能

(1) オブジェクトのクラス化

Class.castメソッドにObjectクラスのインスタンスを渡すことによって、インスタンスはクラス化され、定義されているプロパティは、クラスのメンバーとなります。
(以下、このインスタンスを「クラス定義オブジェクト」と呼びます。)
    var ClassA = Class.cast({
        ...................................
        propertyA: .....,
        ...................................
    });

    // インスタンスの作成
    var a = new ClassA();

Singletonクラスの利用

 アプリケーション全体で1つのクラス・インスタンスを持つようにするには、Class.singleton()を利用します。  Class.cast()と同じく、オブジェクト・インスタンスを引数としますが、得られるのはクラスではなくインスタンスです。

    var instanceA = Class.singleton({
        ...................................
        propertyA: .....,
        ...................................
    });

    // instanceAは、無名クラスの唯一のインスタンスとなります。

(2) 既存クラスからの継承 (Extends)

クラス定義オブジェクト中の「Extends」プロパティに既存のクラスを指定することで、クラス定義オブジェクトに他のクラス(基本クラス)を継承することができます。
継承はあくまでクラス間で行われます。コンストラクタは必要がなければ、定義しなくても構いません。自動的にデフォルトのコンストラクタ(引数なし)が定義されます。
継承は、単一のクラスからのみです。また、基本クラスと重複するプロパティがある場合は、エラーとなります。--> Virtual
    var ClassB = Class.cast({
        ...................................
        Extends: ClassA,
        ...................................
    });

従来のJavascriptのクラスの継承は、プロトタイプ(prototypeプロパティ)へ、スーパークラスのインスタンスをコピーすることで行われます。その決定的な欠陥は、そのままでは、メソッドだけでなく、スーパークラスのプロパティまでがクラス全体で共有されてしまう点です。

    // ClassXの定義
    function ClassX(...) {
        ..............................
        this.data = new Array();
        ..............................
        ..............................
    };

    // ClassYの定義
    function ClassY(...) {
        ..............................
        ..............................
        ..............................
    }

    // ClassXからの継承
    ClassY.prototype = new ClassX(...); // インスタンスを継承するので、メソッドだけでなく、プロパティの実体も含めてプロトタイプに取り込んでしまう。

    var y0 = new ClassY(...);
    var y1 = new ClassY(...);

    // y0.dataとy1.dataは、同じ配列を指してしまう。

 上記の例では、インスタンスy0y1は、共通の配列(data)をプロパティとして持ってしまいます。

 そもそも、インスタンスごとに同じ内容のメソッドを重複してもつことで、無駄なメモリを消費しないように考えらたはずのプロトタイプの機構が、オブジェクトの状態を表すプロパティ(データ)をも取り込んで共有させてしまうという致命的な欠陥を潜在させてしまったのです。

 これを避けて、それぞれのインスタンスが独自のプロパティをもてるようにするには、コンストラクタ内で、スーパークラス(ClassX)のコンストラクタを呼び出さなければなりません。

 これにより、アクセス時に、プロトタイプ内に存在する共有のdataプロパティよりも先に、それぞれのインスタンス内のdataプロパティが検索されるようになります。

// ClassYの定義 function ClassY(...) {
.............................. ClassX.call(this, ...); // スーパークラスのコンストラクタを呼び出すことでインスタンス内に値を取り込む。 ..............................
}

}}}

 こうした回避方法が適切でないさらなる理由は、うっかり別のクラスのコンストラクターを呼び出しても、エラー扱いにはならないということです。

Class.jsは、このようなpインスタンスを基本とした継承機構ではなく、あくまでprototypeからの継承を行うことで、コードを見ただけでは実体が把握しづらかった概念をストーレートに反映できるようにしました。

 具体的には、Extends指定によってスーパークラスは明示的に関連付けられるとともに、スーパークラスのコンストラクタを呼び出さなくても、プロパティは直接、インスタンスに継承されるようになります。

 また、スーパークラスのコンストラクタを呼び出す際も、クラス名を改めて指定してミスを誘発するリスクを排除し、後述する「superClass()」メソッドの利用で、確実に呼び出せるようになります。--> superClass()

(3) インターフェースの実装 (Implements)

クラス定義オブジェクト中の「Implements」プロパティに空メソッドを定義したオブジェクト、または、その配列を指定することで、Javaと同様のインターフェースの機能をもつことができます。
    var InterfaceA = {
        funcA: null     // メソッドは空でよい
    };

    var InterfaceB = {
        funcB: null
    };
    var ClassA = Class.cast({
        ...................................
        ...................................
        Implements: [InterfaceA, InterfaceB],
        ...................................
        ...................................
        funcA: function(...) {     // 未定義だとエラーとなります
            ..............................
            ..............................
        },
        ...................................
        funcB: function(...) {     // 未定義だとエラーとなります
            ..............................
            ..............................
        },
        ...................................
        ...................................
        ...................................
    });
これにより、クラス定義オブジェクトは、インターフェース内に空で定義されているメソッドを、実体として定義することが強制されます。
インターフェースは、複数指定できます。また、あるクラスのインスタンスが特定のインターフェースを実装しているかどうかは、クラス・メソッド「interfaceOf」で調べることができます。
    var a = new ClassA(.....);

    if ( Class.interfaceOf(a, InterfaceA) ) {
        ........................
        ........................
        ........................
    }
    else {
        throw new Error("Instance must implement "InterfaceA" interface.");
    }
外部のインスタンスのメソッドを呼び出す際、期待するメソッドが定義されているか、個別に判定する検査ルーティンを省略できることは、大きなメリットです。
これができないと、期待するプロパティの存在を確認し、それが「関数」であるかを判断しなければなりません。しかし、それだけでは、単に「同じ名前のメソッドもっている」ことしか知ることができません。
インターフェースが実装されていることは、それを期待するクラスからのアクセスを、コード上に明示することになり、クラス間の連携にまつわるデバッグから大幅に開放されることになります。

(4) 固定クラス・メンバー (Const)

クラス定義オブジェクト中の「Const」プロパティ内に定義されたプロパティ、メソッドは、クラス・スコープとなり、かつ値の変更や削除ができなくなります。(ver1.2.0 rev4から、Constメンバーは、getter=リード・オンリーとなりました)。
    var ClassA = Class.cast({
        ...................................
        ...................................
        Const: {
            CLASS_VALUE: XXXXXXXXX,
            ,......................
            MethodX: function(...) {
                ,......................
                ,......................
            },
            ,......................
        },
        ...................................
    });

(5) クラス・メンバー (Static)

クラス定義オブジェクト中の「Static」プロパティ内に定義されたプロパティは、クラス・スコープとなります。Constとは異なり、値の変更やメソッドの差し替え、削除が可能です。
    var ClassA = Class.cast({
        ...................................
        ...................................
        Static: {
            CLASS_DATA1: *********,
            ,......................
            CLASS_METHOD1: function(...) {
                ..........................
                ..........................
            },
            ...............................
        },
        ...................................
        ...................................
        var x = ClassA.CLASS_DATA1;
        ...................................
        ClassA.CLASS_METHOD1(...);
        ...................................
        ...................................
    });

(6) コンストラクタ (newInstance)

コンストラクタは、クラス定義オブジェクト中に「newInstance」という名称の関数として定義します。 コンストラクタ内では、「this.superClass()」メソッドによって、上位のクラス(スーパー・クラス)のコンストラクタを呼び出すことができます。その上位クラスで「this.superClass()」が実行されると、さらに上位のクラスへと連鎖します。
    var ClassB = Class.cast({
        ...................................
        Extends: ClassA,
        ...................................
        newInstance: function(...) {
            ...............................
            this.superClass(...);        // スーパー・クラス"ClassA"のコンストラクタ呼び出し
            ...............................
        },
        ...................................
    });

O'RELLYのJavasScritでは、3階層以上の継承があると、上位クラスへの呼び出しが直接の親以上に遡らず、永久ループになる例が挙げられています。  これはA=>B=>Cという継承が行われた場合、クラスCのインスタンスからスーパークラスBのスーパー・コンストラクタを呼び出せても、あくまで実体がクラスCのインスタンスである以上、クラスBのコンストラクタからクラスAにたどり着くことはできず、繰り返しクラスBのコンストラクタを呼び出し続けることになるからです。当然、クラスBのインスタンスであれば、クラスAにはたどり着けます。

Class.jsでは、この問題は解決されており、継承が何重に行われても、確実に連鎖的にスーパークラスを遡るようになっています。

(7) プライベート・メンバー (Private)

クラス定義オブジェクト中の「Private」プロパティ内に定義されたプロパティは、外部からの直接アクセスができなくなります。
C++やJavaでは、プライベート・メンバーのアクセス制限は単純ですが、Javascriptという足かせのあるClasss.jsでは、値とメソッドとで扱いが異なります。
(a) 値の場合
直接のアクセスができなくなる代わりにゲッター・セッターが自動的に作成されます。名称は、プロパティ名の先頭を大文字にした上で、頭に「get」、「set」がつけられたものとなります。
下記の場合、ゲッター「getPrivateA()」と「setPrivateA()」が自動的に作成されます。
    var ClassA = Class.cast({
        ...................................
        Private: {
            privateA: "....",
            privateX: function(...) {
                ...........................
                ...........................
            },
            ...............................
        },
        ...................................
    });
    var a = new ClassA(...);
    .......................................
    a.setPrivateA(".....");         // セッターの実行
    .......................................
    var x = a.getPrivateA();        // ゲッターの実行
    .......................................
(b) メソッドの場合
プライベート・メソッドは、完全に外部から隠蔽されます。これは、通常のプロトタイプ・チェーンに配置されないことを意味します。
    var a = new ClassA(...);
    .......................................
    .......................................
    a.privateX(...);    // privateXは、ClassAのプロトタイプに存在しないのでエラーになります。
そのため、プライベート・メソッドの使用は、後述する「Loader()」内で定義するメソッドに限定されます。 その他の、公開されているメソッドからは呼び出せません。
    var ClassA = cast({
        ...................................
        Private: {
            ...............................
            privateX: function(...) {
                ...........................
                ...........................
            },
            ...............................
            publicX: function(...) {
                ...........................
                this.privateX(...);                         // エラーになります。
                ...........................
            }
            ...............................
            ...............................
        },
        ...................................
        Loader: function() {
            var privateX = Class.find(this, "privateX");    // プライベート・メソッドを取得

            Class.attach(this, "usePrivate", function() {   // プライベート・メソッドを使用するパブリック・メソッドを定義
                ......................................
                privateX.call(this, ............);          // プライベート・メソッドの呼び出し
                ......................................
            });
        }
    });

    var a = new ClassA(...);

    a.usePrivate();                 // パブリック・メソッドの中でプライベート・メソッドが使用されます。

    a.privateX();                   // エラーになります。
プライベート・メンバーには以下のデメリットや不完全さが残されます。
・ゲッター/セッターの名前は自動的に決まるので、既存のプロパティ名との衝突を避けるようにしなければならない。
・ゲッター/セッターは外部に公開されるので、完全な意味での「隠蔽」にはならない。
・クラス内でもゲッター/セッターを通してしかアクセスできなくなる。
・既存のメソッドの中からは呼びせない。
・記法が、通常のメソッドの大きく異なる。
プライベート・メンバーの使用は、クラス内にある重要な情報をブラウザの開発ツールで安易に覗けないようにしたり、簡単なコードで書き換えたりできなくすることで、「バグや不正な改変を減少」させることが第一の目的です。
データの重要度やパフォーマンスを考えながら、慎重に検討した上で効果的に利用されることを推奨します。

(8) 仮想メンバー (Virtual)

クラス定義オブジェクト中の「Virtual」プロパティ内に定義されたプロパティは、このクラスを継承したサブ・クラスでオーバーライドする(同名のメソッドやプロパティで上書きする)ことができます。Class.jsでは、C++同様、明示的に仮想メンバーにしない限り、オーバーライドはできません。
その理由は、継承先のクラスで「誤って」同じプロパティ名を使用した場合、それを検証する方法がないと、デバッグの負担が増大することになりかねないからです。
(Javaでは、すべのメソッドはデフォルトで仮想メソッドですが、final修飾子によって、オーバーライドが抑制できるようになっています。)
    var ClassA = Class.cast({
        ...................................
        Virtual: {
            ..............................
            methodA: function(...) {
                ....................
            },
            ..............................
            ..............................
        },
        ...................................
        methodB: function(...) {
            ...............................
        },
        ...................................
    });
    var ClassB = Class.cast({
        Extends: ClassA,        // ClassAを継承
        ...................................
        methodA: function(...) {    // OK 仮想メソッドなのでオーバーライド可能
            ...............................
            this.superMethod(this.methodA, ...);   // 基本クラスのメソッド呼び出し。
            ...............................
        },
        ...................................
        ...................................
        methodB: function(...) {    // ERROR 基本クラスとの名前の衝突の例外が発生する。
            ...............................
        },
        ...................................
    });
仮想メンバーは、一度定義されると、何重に継承されても仮想メンバーのままです。
後述する「抽象メンバー」とは異なり、『実体』を持ちますが、「継承先でカスタマイズができる」ことを示しています。
これは、クラスを設計する上で重要なことです。
仮想メンバーと非仮想メンバーとに、アクセス・パフォーマンスに差はありません。

(9) 抽象メンバー (Abstract)

クラス定義オブジェクト中の「Abstract」プロパティ内に定義されたプロパティが存在すると、クラスは「抽象クラス」となります。
抽象クラスは、そのままインスタンス化することはできず、必ず継承してサブ・クラスを通して利用します。
抽象メンバーは(基本的にメソッド)は、実体を持ちません。これらは、継承先のクラスで実体を定義しなければなりません。
抽象メンバーが未定義だと例外が発生し、クラス自体の構築が中断されます。
    var ClassA = Class.cast({
        ...................................
        Abstract: {
            ..............................
            methodA: null,  // 実体は定義しない
            ..............................
            ..............................
        },
        ..................................
    });
    var ClassB = Class.cast({
        Extends: ClassA,        // 抽象クラスClassAを継承
        ...................................
        methodA: function(...) {                // 未定義だとクラス構築時に例外が発生
            ...............................
            ...............................
        },
        ...................................
    });
抽象メンバーは、一度、直接の継承クラスで定義されると、あとは仮想メンバーと同じ効果を持ちます(常にオーバーライド可能)。 抽象クラスと、インターフェースの違いは、インターフェースはすべてのプロパティは「実体をもたない」のに対し、抽象クラスでは「一部を穴あき」にした状態になっている点です。

 たとえば、「図形」を表現するクラスでは「描画」メソッドは抽象メソッドにし、実際の描画処理は、サブクラスの「三角」、「円弧」、「四角」で定義する(ことが義務付けられる)というように使用します。

(10) クラスローダー (Loader)

クラス定義オブジェクト中の「Loader」プロパティに定義されたメソッド(引数なし)は、Class.cast()メソッドによるクラス構築の最終段階で一度だけ実行されます。
クラスの構築時には、アプリケーションもインスタンスも存在しません。したがって、クラスローダーの役割は、「クラス・メンバー(Static)中の『値』の初期化」となります。
その対象は、自クラスにとどまらず、クラス・メソッドを通して、構築済みの他クラスも含まれます。
    var ClassA = Class.cast({
        ...................................
        Static: {
            ..............................
            propertyA: null,
            ..............................
            setPropertyA: function(...) {
                this.propertyA = ...;
            },
            ..............................
        },
        ...................................
    });
    .......................................
    .......................................

    var ClassB = Class.cast({
        ...................................
        Static: {
        ...................................
            propertyB: null,
        ...................................
            setPropertyB: function(...) {
                this.propertyB = ...;
            },
        ...................................
        },
        ...................................
        ...................................
        Loader: function() {
            ...............................
            var x = .......................
            this.setPropertyB(x);       // ClassBはこの時点で未定義なのでthisでアクセス
            ...............................
            var y = .......................
            ClassA.setPropertyA(y);     // ClassAは構築済みなので、アクセス可能
            ...............................
        },
        ...................................
    });

(11) プロトタイプのインポート (Imports)

クラス定義オブジェクト中の「Imports」プロパティで、外部のオブジェクトまたはその配列を指定すると、それらのプロパティが、クラス定義オブジェクトに取り込まれます。
取り込み方法には以下の2つのルールがあります。
(a) クラス定義オブジェクトのプロパティをオーバーライドすることはできない。
(b) インポートされるオブジェクト間では、後で指定した方のプロパティが優先される。
    var ObjectX = {
        ...................................
        property0: .....,
        ...................................
        method0: function(...) {
            ...............................
            ...............................
        },
        ...................................
    };
    .......................................
    var ObjectY = {
        ...................................
        property1: .....,
        ...................................
        method0: function(...) {                // ObjectXのmethod0は、取り込まれない
            ...............................
            ...............................
        },
        ...................................
        method1: function(...) {
            ...............................
            ...............................
        },
        ...................................
    };
    .......................................
    var ClassA = Class.cast({
        ...................................
        Imports: [ObjectX, ObjectY],
        ...................................
        method1: function(...) {                // ObjectYのmethod1は、取り込まれない
            ...............................
            ...............................
        },
        ...................................
    });
インポート機能は、一見、『多重継承』のように見えますが、プロパティの取り込み後、もとのオブジェクトの存在は不可視となります。
また、名前の衝突の可能性が高いので、再利用性も低くなります。さらに、衝突の結果、どのオブジェクトのプロパティが採用されたかも、判別が困難です。使用には、細心の注意が必要といわざるを得ません。
Class.jsでは、Importsの使用は、積極的に推奨しません。継承やインターフェースを活用するか、クラスのインスタンスとして取り込むか、後述する内部クラスとして定義するなど、別の方法を考慮した方がよいでしょう。

(12) 内部クラス

クラス定義オブジェクト中のプロパティの値を「Class.cast()」メソッドの呼び出しにすることで、クラス内にクラスを構築することができます。
内部クラスには、以下の2通りがあり、それぞれ利用方法が異なります。
(a) Staticプロパティ内で定義
内部クラスは外側のクラスを通じて公開され、外部からアクセスしてインスタンスの生成が可能となります。
外側のクラスとの関連が密接でありながら、独立してインスタンスの生成して利用す場合に適しています。
    var ClassA = Class.cast({
        ...................................
        Static: {
            ...............................
            InnerClassA: Class.cast({           // 公開内部クラス
                ...........................
                newInstance: function(...) {
                    .......................
                    .......................
                },
                ...........................
                innerMethodA: function(...) {
                    .......................
                    .......................
                },
                ...........................
            });
            ...............................
            getInnerAInstance: function(...) {  // クラス・メソッドを通して生成
                return new this.InnerClassA(...);
            },
            ...............................
        },
        ...................................
    });
    .......................................
    // インスタンスの生成
    var ia0 = new ClassA.InnerClassA(....);
    var ia1 = ClassA.getInnerAInstance(....);
    // メソッド呼び出し
    ia0.innerMethodA(...);
    ia1.innerMethodA(...);
(b) 通常のプロパティで定義
このクラスは、外側のクラスのインスタンスの生成時に構築されます。生成された内部クラスのインスタンスは、通常のインスタンス同様に外部から操作が可能です。
この手法は、従属関係の明示化とともに、シングルトン・モデルのように外側のクラスのインスタンス前提として利用する場合に適しています。
    var ClassB = Class.cast({
        ...................................
        InnerClassB: Class.cast({               // 内部クラス
            ...............................
            newInstance: function(...) {
                ...........................
                ...........................
            },
            ...............................
            innerMethodB: function(...) {
                ...........................
                ...........................
            },
            ...............................
        }),
        ...................................
        methodB: function(...) {
            ,.................................
            var ib = new this.InnerClassB(...);  // インスタンスからのみ生成可能
            ,.................................
            ib.innerMethodB();
            ,.................................
        },
        ...................................
        getInnerBInstance: function(...) {      // インスタンスメソッドを通して生成
            return new this.InnerClassB(...);
        },
        ...................................
    });
    .......................................
    // インスタンスの生成
    var b = new ClassB(...);
    var ib0 = b.getInnerBInstance(...);
    var ib1 = new b.innerMethodB(...);
    // メソッド呼び出し
    ib0.innerMethodB(...);
    ib1.innerMethodB(...);

(13) superClass()メソッドとsuperMethod()メソッド

他のクラスを継承したクラスには、自動的に「superClass()」と「superMethod()」メソッドが定義されます。
superClass()は、コンストラクタ内でのみで使用し、直接のスーパークラスのコンストラクタを呼び出します。

 一方、superMethood()は、オーバーライドされたスーパークラスの仮想メソッドを実行します。--> Virtual

    var ClassA = Class.cast({
        ...................................
        // コンストラクタ
        newInstance: function(...) {
            ...............................
            ...............................
        },
        ...................................
        Virtual: {
            ...............................
            methodX: function(...) {
                ...........................
                ...........................
            },
            ...............................
        },
        ...................................
    });
    .......................................
    var ClassB = Class.cast({
        Extends: ClassA,
        ...................................
        // コンストラクタ
        newInstance: function(...) {
            ...............................
            // ClassAのコンストラクタを呼び出す
            // thisがサブ・クラスのインスタンスでもClassAへの遡及は保証される。
            this.superClass(...);
            ...............................
        },
        ...................................
        methodX: function(...) {                // ClassAのmethodXがVirtualなのでオーバーライド可能
            ...............................
            // ClassAのインスタンス・メソッドを呼び出す(第1引数は、自身のメソッド)
            this.superMethod(this.MethodX, ...);
            ...............................
        },
        ...................................
    });
    .......................................
    var ClassC = Class.cast({
        Extends: ClassB,
        ...................................
        // コンストラクタ
        newInstance: function(...) {
            ...............................
            // ClassBのコンストラクタを呼び出す
            this.superClass(...);
            ...............................
        },
        ...................................
        methodX: function(...) {                // ClassAの系譜にあるのでオーバーライド可能
            ...............................
            // ClassBのインスタンス・メソッドを呼び出す。
            // 連鎖的に、ClassBのmethodX()も実行される。
            this.superMethod(this.methodX, ...);
            ...............................
        },
        ...................................
    });
    .......................................

(14) Beanクラス

BeanとはJavaBeansの仕様を参考にしたものです。JavaBeansでは、その仕様にのっとって作成された部品クラスのことを指しますが、Class.jsでは、オブジェクト中のすべての値をプライベート・メンバーにしたクラスにしたものを、こう呼びます。
具体的には、Class.beanメソッドにObjectクラスのインスタンスを渡すことによって、クラスを構築します。
定義されている値のプロパティは、すべてプライベート・メンバーとなり、Privateプロパティのルール(上記参照)にしたがって、ゲッター/セッターがメンバーごとに定義され、さらに引数なしのコンストラクタが定義されます。
一方、メソッドについては、そのまま外部からのアクセス可能なメソッドとして機能しますが、値のメンバーに対しては、アクセサ経由でしかアクセスできなくなります。
    BeanX = Class.bean({
        valueA: .....,
        valueB: .....
        ...................................
        methodA: function(...) {
            ...............................
            this.valueA = ....;                 // ERROR valueAは隠蔽されるので直接アクセス禁止
            ...............................
            this.setValueA(....);               // OK valueAへはアクセサ経由でアクセス
            ...............................
        },
        ...................................
    });
    .......................................
上記の例では、valueA、valueBは、プライベート・メンバーとなって外部からのアクセスが遮断され、アクセサ「getValueA()」、「setValueA()」、「getValueB()」、「setValueB()」、および引数なしのコンストラクタが定義されます。
    var x = new BeanX();
    x.setValueA(...);       // 値はアクセサ経由
    x.setValueB(...);       // 値はアクセサ経由
    .......................................
    .......................................
    x.methodA(...);         // メソッドは呼び出し可能
    .......................................
    .......................................
    console.log("value A is --> " + x.getValueA());
    console.log("value B is --> " + x.getValueB());
    .......................................
セキュリティ性の高いクラスが生成できる点と、アクセサの定義作業を省略できる点で、Beanはデータを保持するクラスに適しているといえます。
Beanクラスのクラス定義オブジェクトでは、'Extends'、 'Implements'、 'Static'などの特殊なブロックは、それらのルールが示す効果を持たず、単なるプライベート・メンバーとみなされます(アクセサが定義されてしまいます)。

(16) ユーティリティ・メソッド

fix

 オブジェクトのプロパティを、リード・オンリーにします。

    Class.fix(object, "property");

shield

 オブジェクトにゲッタを設定します。値自体をオブジェクトから隠蔽し、参照のみを行いたい場合に利用します。ゲッターは変更不可です。

    Classs.shield(object, "property", value);
    ........................................
    ........................................
    var refval = object.property;       // valueを取得

    console.log(object);                // コンソールからvalueは参照できない

    object.property = .............;    // 変更は反映されない

attach

 オブジェクトにメソッドを追加します。

    Class.attach(object, function(...) {.........................});

find

 クラスから名前でメソッドを検索します。

    var meth = Class.find(ClassX, "function_name");

(16) Node.jsで利用する場合

 Node.jsで使用する際は、以下のようにrequire()によって取り込みます。

    .........................................................
    .........................................................
    var Class = require("[パス]/Class-XX.XX.XX-min.js").main;
    .........................................................
    .........................................................
    var MyClass = Class.cast({
        .....................................................
        .....................................................
        .....................................................
    });

    .....................................................
    .....................................................
    var my_obj = new MyClass(...);
    .....................................................
    .....................................................