高度なクラス作成
更新 : 2007 年 11 月
JScript のクラスを定義するときに、プロパティを割り当てることができます。また、定義したクラスは、続いて他のクラスからも継承できます。フィールドに似たクラス メンバであるプロパティを使用すると、データへのアクセス方法を詳細に制御できます。継承を使用することにより、クラスは他のクラスを拡張 (または、他のクラスに動作を追加) できます。
クラスの定義で、クラスのインスタンスに expando プロパティをサポートさせることができます。つまり、クラス ベースのオブジェクトは、オブジェクトに動的に追加されるプロパティとメソッドを持つことができます。クラス ベースの expando オブジェクトは、プロトタイプ ベースのオブジェクトと同様の機能をいくつか提供します。
クラスとプロパティ
JScript では、function get ステートメントおよび function set ステートメントを使用してプロパティを指定します。いずれかのアクセサまたは両方のアクセサを指定して、読み取り専用、書き込み専用、または読み取り/書き込みのプロパティを作成できます。ただし、書き込み専用のプロパティはあまり使用されず、クラスのデザインに問題があることを示している場合があります。
呼び出し元のプログラムは、フィールドにアクセスする場合と同じ方法でプロパティにアクセスします。主な違いは、プロパティではアクセスの実行に取得関数と設定関数を使用するのに対し、フィールドには直接アクセスすることです。クラスでプロパティを利用すると、有効な情報だけが入力されていることを確認したり、プロパティの読み取りや設定が実行された回数を追跡したりできます。また、動的な情報を返すこともできます。
通常、プロパティはクラスのプライベート フィールドまたはプロテクト フィールドにアクセスするために使用されます。プライベート フィールドには private 修飾子が指定され、このフィールドには同じクラスの他のメンバしかアクセスできません。プロテクト フィールドには protected 修飾子が指定され、このフィールドには同じクラスまたは派生クラスのメンバしかアクセスできません。詳細については、「JScript の修飾子」を参照してください。
次の例では、プロパティを使用してプロテクト フィールドにアクセスしています。フィールドは外部コードによって値が変更されないように保護されますが、派生クラスからはアクセスできます。
class Person {
// The name of a person.
// It is protected so derived classes can access it.
protected var name : String;
// Define a getter for the property.
function get Name() : String {
return this.name;
}
// Define a setter for the property which makes sure that
// a blank name is never stored in the name field.
function set Name(newName : String) {
if (newName == "")
throw "You can't have a blank name!";
this.name = newName;
}
function sayHello() {
return this.name + " says 'Hello!'";
}
}
// Create an object and store the name Fred.
var fred : Person = new Person();
fred.Name = "Fred";
print(fred.sayHello());
このコードの出力は次のようになります。
Fred says 'Hello!'
Name プロパティに空白の名前を代入すると、エラーが発生します。
クラスからの継承
他のクラスを基にクラスを定義する場合は、extends キーワードを使用します。JScript では、ほとんどの共通言語仕様 (CLS: Common Language Specification) 準拠のクラスを拡張できます。extends キーワードを使用して定義されたクラスは派生クラスと呼ばれます。また、拡張元のクラスは基本クラスと呼ばれます。
次の例では、新しい Student クラスを定義しています。このクラスは、前の例の Person クラスを拡張しています。Student クラスでは、基本クラスで定義されている Name プロパティを再利用しています。また、新しい sayHello メソッドを定義して、基本クラスの sayHello メソッドをオーバーライドします。
// The Person class is defined in the code above.
class Student extends Person {
// Override a base-class method.
function sayHello() {
return this.name + " is studying for finals.";
}
}
var mary : Person = new Student;
mary.Name = "Mary";
print(mary.sayHello());
このコードの出力は次のようになります。
Mary is studying for finals.
派生クラスでメソッドを再定義しても、基本クラスの対応するメソッドは変更されません。
expando オブジェクト
汎用オブジェクトを expando にするだけの場合は、Object コンストラクタを使用します。
// A JScript Object object, which is expando.
var o = new Object();
o.expando = "This is an expando property.";
print(o.expando); // Prints This is an expando property.
クラスの 1 つを expando にする場合は、expando 修飾子を指定してクラスを定義します。expando メンバには、インデックス ([]) 表記を使用してアクセスできます。ドット (.) 表記ではアクセスできません。
// An expando class.
expando class MyExpandoClass {
function dump() {
// print all the expando properties
for (var x : String in this)
print(x + " = " + this[x]);
}
}
// Create an instance of the object and add some expando properties.
var e : MyExpandoClass = new MyExpandoClass();
e["answer"] = 42;
e["greeting"] = "hello";
e["new year"] = new Date(2000,0,1);
print("The contents of e are...");
// Display all the expando properites.
e.dump();
このプログラムの出力は次のようになります。
The contents of e are...
answer = 42
greeting = hello
new year = Sat Jan 1 00:00:00 PST 2000