JScript.NET  新JavaScript入門  JavaScript,Neo-Generation  DOM  WSH  掲示板  表紙
関数 
Written 7/7/03
JScript.NET
クラス
JScriptにはオブジェクト指向っぽい言語機能として ユーザ定義オブジェクトというものがありましたが、 JScript.NETではちゃんとしたクラスが導入されました。
このページでは基本的な機能を紹介します。
ここでは分数クラスを作りますが、 参考までに以前に作った旧分数オブジェクトを紹介しておきます。
    分数オブジェクト
 
見比べてください。
クラスの定義
分数を扱いやすくするためにFractionクラスを作ってみました。 この例はオブジェクト指向としては適切ではないかもしれませんが。
    fraction1.js
    ---------------------------------------------------------
    class Fraction {
        private var a : long;
        private var b : long;
        function Fraction() { a = 0; b = 1; }
        function Fraction(a : long) { this.a = a; b = 1; }
        function Fraction(a : long, b : long) {
            this.a = a; this.b = b;
            this.normalize();
        }
        private function normalize() { //約分
            ...
        }
        function ToString() : String {
            ...
        }
        ...
    }
    
    var a : Fraction = new Fraction(2, 6);
    print(a);
 
クラスを作るときは、
    class Fraction {
        ...
    }
 
のようにして、クラス名を指定して、中に定義を書いていきます。
そうすると、下から2番目にあるように、 組み込みオブジェクトと同じように使えます。
    var a : Fraction = new Fraction(2, 6);
 
これは変数aを、分子2、分母6の分数オブジェクトとして初期化しています。
プロパティ
プロパティは普通にvarを使って定義します。
    private var a : long;
    private var b : long;
 
ここではaが分子、bが分母を表しています。
頭にprivateという修飾子がついているのは、 外から直接この値にアクセスできないようにするためです。
    var a : Fraction = new Fraction(2, 6);
    a.b = 2;        //コンパイルエラー
 
代わりにpublicをつける、 または何もつけないと外からアクセスできます。
なぜこんなことをしたいかというと、 分母と分子は常に約分されているという前提で色々な計算をしたいからです。 例えば、1/3で分子を勝手に3にしたら3/3になってしまいます。
なんにせよ、 基本的にはprivateにしておいた方がよいようです。
ただ、外から見るぐらいはいいだろうということで、 次のようなステートメントが用意されています。
    class Fraction {
            ...
        function get Bunsi() { return a; }
            ...
    }
 
こうしておくと、次のようにアクセスできます。
    var a : Fraction = new Fraction(2, 6); // 1/3
    print(a.Bunsi);       //1
 
これとセットで次のようにfunction setを定義すると プロパティの変更もできます。
    class Fraction {
            ...
        function get Bunsi() : long { return a; }
        function set Bunsi(a : long) {
            this.a = a;
            normalize();    //約分
        }
            ...
    }
    
    var a : Fraction = new Fraction(2, 6);
    a.Bunsi = 3;
    print(a);    //1
 
function getfunction set は対になっていることに注意しましょう。
    function get Bunsi() : long { ... }
    function set Bunsi(a : long) { ... }
 
こうしておけば1/3の分子に3を代入しても1/1になります (ちょっとDateオブジェクトに似ている?)。 しかし、このクラスではsetは使わないことにします。
コンストラクタ
オブジェクトを生成するための関数です。
Fractionクラスでは引数によって3つのコンストラクタを用意しています。
    class Fraction {
            ...
        function Fraction() { a = 0; b = 1; }
        function Fraction(a : long) { this.a = a; b = 1; }
        function Fraction(a : long, b : long) {
            this.a = a; this.b = b;
            this.normalize();
        }
            ...
    }
 
実際にオブジェクトを生成するには、
    var f : Fraction;
    f = new Fraction(1, 3);
 
などとします。 上の例では引数の整合性から3番目のコンストラクタが実行されます。
メソッド
メソッドは普通にfunctionを使って定義すればよいです。
    class Fraction {
            ...
        private function normalize() {
            ...
        }
        function ToString() : String {
            if(b == 1)
                return a.ToString();
            else
                return a + "/" + b;
        }
            ...
    }
 
privateが頭についていると、 プロパティと同じようにクラス内でしか使えません。 publicがついている、 またはどちらもついていなければ外から使えます。
        static function op_Addition(a : Fraction, b : Fraction) : Fraction {
            return new Fraction(a.a * b.b + a.b * b.a, a.b * b.b);
        }
 
このように頭にstaticがついているのは、 インスタンスがいらないということです。 すなわち次のように使います。
    var a : Fraction = new Fraction(1, 3);
    var b : Fraction = new Fraction(1, 5);
    print(Fraction.op_Addition(a, b));
 
staticがつかないバージョンと較べてください。
            ...
        function Add(f : Fraction) : Fraction {
            return new Fraction(a * f.b + b * f.a, b * f.b);
        }
            ...
    print(a.Add(b));
 
演算子のオーバーロード
演算子のオーバーロードは、どうやらできないみたいです。
こういうときは代わりにC#で書きましょう。 これを利用すると演算子が使えます。
    fraction.cs
    ------------------------------------------------------------------
    public class Fraction {
        private long  a;
        private long  b;
        public Fraction() { a = 0; b = 1; }
        public Fraction(long x) { a = x; b = 1; }
        public Fraction(long x, long y) { a = x; b = y; normalize(); }
            ...
        //等値演算子
        public static bool operator ==(Fraction f1, Fraction f2) {
            return f1.a == f2.a && f1.b == f2.b;
        }
            ...
    }
 
JScript.NETとあんまり変わらないように書けるので難しくないでしょう。
このクラスはなるべくオーバーフローしないように作っています。 それでもまだかなり甘いのですが。 そのうち修正すると思います。
これを次のようにコマンドラインからコンパイルしてDLLを作ります。
    >csc /target:library fraction.cs
 
fraction.dllというファイルができていることを確認しましょう。
    fraction_test.js
    ------------------------------------------------------------------
    var f1 = new Fraction(1, 3);
    var f2 = new Fraction(2, 6);
    print(f1 == f2);      //true
 
これを次のようにコンパイルします。
    >jsc /reference:fraction.dll fraction_test.js
 
このようにするとfraction.dllを利用できて、Fractionクラスが使えます。
実は、VB.NETはこのようにしても演算子が使えないので、 JScript.NETはかなりましです。
prev, next, exit