アンダース氏が設計した新言語による次世代JavaScript開発とは?:特集:TypeScript(プレビュー版)概説(前編)(3/3 ページ)
JavaScript系の新言語である「TypeScript」とは何か? その特徴と言語仕様を説明。今回はクラスの基礎を解説する。
クラス・メンバの基礎
●メンバ変数
まずは、次の2種類のメンバ変数について説明する。
- インスタンス・メンバ変数: クラス内に宣言された変数のこと。
- 静的メンバ変数: クラス内に「static」修飾子付きで宣言された変数のこと。
今回のサンプル・コードで言うと、次の2行がメンバ変数の宣言である。
private message: string; // インスタンス・メンバ変数
public static count: number; // 静的メンバ変数
ここでも、コンストラクタ・パラメータと同じように、「private」や「public」といったアクセシビリティを指定できる。先ほどと違うのは、クラス・メンバの既定のアクセシビリティが「public」であるということだ(※コンストラクタの場合は「private」だった)。つまり、アクセシビリティを省略すると、そのメンバ変数は自動的にクラス外に公開されることになる。
なお、“private”以外のメンバ変数のアクセシビリティは省略するのが一般的のようだ。つまり先ほどの2行目のコードは、一般的には「static count: number;」と記述する方が一般的である。
「: string」などの型注釈は、コンストラクタ・パラメータと同じ使い方なので、説明を割愛する。
○インスタンス・メンバと静的メンバ
通常のメンバ変数は、インスタンス化されたオブジェクトごとに保持されるが、static修飾子を付けた静的メンバ変数(=例えば上記のコードの「count」)は全てのインスタンスで共通のメンバ変数となる(※静的に定義されるので、インスタンス化しなくても、このメンバ変数にはアクセスできる)。
上記のインスタンス・メンバ変数や静的メンバ変数にアクセスしているのが、下記のコード部分である。
constructor(public name: string, public price: number) {
// インスタンス・メンバ変数へのアクセス
this.message = name + "の価格は、" + price + "円です。";
Chair.count++; // 静的メンバ変数へのアクセス
}
まず、「this.message」と記述されたインスタンス・メンバ変数の方から見ていくと、「this」キーワードによりクラス・インスタンス内のメンバ変数にアクセスできることが分かる(なお、この「this」は省略できない)。
一方、「Chair.count」と記述された静的メンバ変数の方を見ると、「Chair」とクラス名を明記してクラス内の静的メンバ変数にアクセスできることが分かる。
○メンバ変数の初期値の設定
この例では、コンストラクタ内で各種メンバ変数を初期化しているが、メンバ変数の宣言時に初期値を指定することもできる。次のコードはその例である。
private message: string = "初期化用の文字列です。";
public static count: number = 0;
【コラム】Array(配列)型のメンバ変数の記述方法
メンバ変数でJavaScript言語の配列型を指定する場合は、下記のようになる。
public static colors1: string[] = ["赤", "青", "緑"]; // 配列リテラルの場合
public static colors2: string[] = new Array("赤", "青", "緑");
●メンバ関数
メンバ関数についても、メンバ変数と同じように次の2種類がある。
- インスタンス・メンバ関数: クラス内に宣言された関数のこと。
- 静的メンバ関数: クラス内に「static」修飾子付きで宣言された関数のこと。
今回のサンプル・コードで言うと、次のコードがメンバ関数の宣言である。
// インスタンス・メンバ関数
public showMessage(): void {
alert(this.message);
}
// 静的メンバ関数
public static getCounter(): string {
return "クラスがインスタンス化された回数: " + count;
}
「private」や「public」といったアクセシビリティ指定は、メンバ変数の場合と全く同じである。
「: void」や「: string」などの型注釈は、関数の戻り値(=returnキーワードで返されるオブジェクト)の型を指定している。この型注釈を省略した場合、「return」の記述がなければ常に「void」型となり、記述があればその戻り値の型に自動的になる(=これは「型の推論(Type Inference)」と呼ばれる機能。例えば「getCounter」関数の「: string」を省略しても、戻り値の型は自動的にstring型になる)。「: void」は常に明記する必要がないので、一般的には省略されて、上記のコード例で言うと「showMessage() { …… }」のように記述される。
このコード例では関数パラメータはないが、パラメータの記述方法は前述のコンストラクタ・パラメータと基本的に同じである。ただし関数パラメータの場合、アクセス修飾子は指定できないので注意してほしい(そのため、クラス外部に公開するメンバ変数は、関数パラメータでは宣言できない)。例えば「showMessage(name: string, price: number) { …… }」のようにして関数パラメータを定義できる。
○関数パラメータやコンストラクタ・パラメータのデフォルト値の設定
メンバ関数の関数パラメータや、前述のコンストラクタ・パラメータの宣言時には、デフォルト値(=初期値)を指定することもできる(その値からパラメータの型も推論される)。次のコードはその例である。
showMessage(arg1 = 100) { …… }
constructor(public name = "test") { …… }
デフォルト値を指定したメンバ関数やコンストラクタを呼び出す際に、デフォルト値のままでよい場合は、そのパラメータへの引数指定を省略できる。例えば上記のコード例で言うと、arg1パラメータへの指定を省略して「showMessage();」のようにして呼び出せる。
【コラム】コールバック関数の記述方法について
関数パラメータに別の関数を指定して、関数内などでその別の関数を呼び出したい場合がある。そのような“別の関数”のことを、「コールバック関数(Callback Function)」と呼ぶが、その関数の型を指定するには、「=>」(=アロー関数式: arrow function expressions)を使って記述する。具体的には、次のようなコードになる。
class Chair {
……省略……
static CallbackTest(callback: (arg1: string) => void) {
callback("コールバックされました!");
}
……省略……
}
Chair.CallbackTest((arg1: string): void => { alert(arg1); });
上記のコードを見ると、CallbackTest静的メンバ関数のcallbackパラメータには、「(arg1: string) => void」という関数型リテラル(Function Type Literals)による型注釈が指定されている。「=>」の左辺にある「( …… )」内には関数パラメータ群(この例ではstring型の「arg1」の1つ)が記述されており、その右辺には戻り値の型(この例では「void」)が記述されている。
CallbackTest静的メンバ関数を呼び出すには、先ほど説明した型を持つ関数オブジェクトを、関数パラメータに渡す必要がある。その際には、いくつかの記述方法を採用できるが、上記のコード例では、「=>」の左辺に関数の型を指定し、その右辺に関数の中身を記述している(functionキーワードを省略する、この記述方法は、「アロー関数式: Arrow Function Expressions」と呼ばれ、ECMAScript 6で採用予定である)。
●メンバ・アクセサ
今回のサンプル・コードには含まれていないが、メンバ変数やメンバ関数のほかに、「メンバ・アクセサ(Member accessor)」と呼ばれるクラス内のメンバも定義できる。
これについても同様に、次の2種類がある。
- インスタンス・メンバ・アクセサ: クラス内に宣言されたアクセサのこと。
- 静的メンバ・アクセサ: クラス内に「static」修飾子付きで宣言されたアクセサのこと。
メンバ・アクセサは、C#言語では「プロパティ(Properties)」と呼ばれているものとほぼ同等で、プロパティ値を読み取るためのgetアクセサと、書き込むためのsetアクセサの両方、もしくは片方を宣言することで定義できる。次のコードは、「size」という名前のメンバ・アクセサを定義している例である。
class Chair {
// メンバ・アクセサの宣言
private _size = 0; // 初期値から推論されるので、型注釈は省略
// getアクセサの宣言
public get size(): number {
return this._size;
}
// setアクセサの宣言
public set size(value: number) {
this._size = value;
}
}
var myChair = new Chair();
myChair.size = 100; // setアクセサ利用
alert(myChair.size.toString()); // getアクセサ利用
ここまでの説明を理解していれば、特にこのコードを理解するのは難しくないだろう。説明は割愛する。
このTypeScriptコードを正常にJavaScriptコードに変換するには、ES5(ECMAScript 5)モードでコンパイルする必要があるので注意してほしい。通常はES3モードでコンパイルされるので、Visual Studio 2012のIDEでビルドするとエラーになってしまう。
これを回避するには、コマンドラインの場合は、下記のようにコマンドを指定すると正常にコンパイルできる。
tsc app.ts --target ES5
Visual Studio 2012のIDEでビルドする場合は、上記と同じコマンドが実行されればよいので、プロジェクト・ファイル(今回の例では「FirstTypeScriptHTMLApp.csproj」ファイル)をテキスト・エディタなどで開き、
<Exec Command="tsc$(TypeScriptSourceMap) @(TypeScriptCompile ->'"%(fullpath)"', ' ')" />
というコードを、
<Exec Command="tsc$(TypeScriptSourceMap) @(TypeScriptCompile ->'"%(fullpath)" --target ES5', ' ')" />
と書き換えると(具体的には「 --target ES5」を追記すると)、正常にビルドできるようになる。
前編はここまでとする。後編では、引き続きクラスの機能解説として「継承」について取り上げる。また、インターフェイスやモジュールについても説明する。
Copyright© Digital Advantage Corp. All Rights Reserved.