C#開発者のための最新JavaScript事情(クラス定義編):特集:C#×JavaScript(2/4 ページ)
本稿では、C#とJavaScriptにおけるクラス定義を比較し、TypeScriptやECMAScript 2015でJavaScriptプログラミングがどう変わるかを見ていく。
Hello World
最初に見るのは「Hello World」だ。コードを以下に示す。
using System;
namespace cs
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("hello from Program.Main in Program.cs");
Console.ReadLine();
}
}
}
見慣れたコードである。まずはこれと同等なプログラムをJavaScript 5/TypeScript/ECMAScript 2015で記述してみよう。もちろん、これらはスクリプト言語なので、実際には「console.log("Hello World");」なり「alert("Hello World");」なりの1行で済んでしまうのだが、そこはそれ。プログラムの構造も同様なものにしてみよう。
ただし、ここでは「using」による名前空間の導入、「namespace」による名前空間の指定は保留としておく。つまり、JavaScript 5/TypeScript/ECMAScript 2015でクラスをどのように定義するかに着目する。
JavaScript 5でのクラス定義
では、JavaScript 5でのクラス定義から見てみよう。厳密には、JavaScriptはクラスベースのオブジェクト指向プログラミング言語ではなく、プロトタイプを利用してクラスと同様な機構を実現する。以下で行っているのはクラス定義「的」な処理だ。
var Program = (function() { // 即実行関数の実行結果を変数Programに代入
function Program() {} // コンストラクターの定義
Program.Main = function() { // 静的メソッドの定義
console.log("hello from Program.Main");
};
return Program; // コンストラクターが戻り値
})(); // 即時実行関数を実行
Program.Main();
JavaScript 5でプログラムを記述している方には説明の必要もないだろうが、ざっくりと解説をしておこう。
大枠ではこのコードは「var Program = (function() { ... })();」となっている。これはかっこで囲まれた関数(無名関数)を実行した結果を変数Programに代入するものだ(このようにかっこで囲まれて定義され、最後にかっこを付けて、呼び出される形式の関数のことを「即時実行関数」と呼ぶ)。そして、無名関数の内部では何もしない関数Programを定義し、その関数のMainプロパティにコンソールに出力を行う関数をセットして、最後に関数Programを戻り値としている。よって、変数Programには戻り値となった関数Programが代入される。JavaScript 5では、このような記述をクラス定義の代わりとして使える。
即時実行関数内で定義されている関数Programは、C#におけるコンストラクターとして機能する。ところで、JavaScriptでは関数もオブジェクトであり、プロパティを設定できる。これを利用して、「Program」を名前空間のように扱い、そこに静的メソッド(スタティックメソッド/クラスメソッド)を定義しているのが、「Program.Main = ...」という部分になる。
Program.Main関数は静的メソッドなのでインスタンスがなくても呼び出せる。これが最後の「Program.Main()」呼び出しだ。
このように、JavaScript 5でクラスベースのオブジェクト指向プログラミングに近いことをやろうとすると、C#に慣れた人にとってはかなり面倒なことになる。そこで、TypeScriptやECMAScript 2015では、クラスベースのオブジェクト指向プログラミングも行えるように構文が拡張されたのである。というわけで、次にこれらの言語でクラス定義がどのようになるかを見てみよう。
ここで注意しておきたいのは、TypeScriptにしてもECMAScript 2015にしても、従来のJavaScriptに対してクラスを利用したプログラミングも可能になるような構文が拡張されたものであり、JavaScriptの本質には変わりはないという点だ。つまり、プロトタイプを基にオブジェクトを生成し、個々のオブジェクトを操作するというスタイルには本来的には変わりはない。
TypeScript/ECMAScript 2015でのクラス定義
まずはTypeScriptから見てみよう。冒頭でも述べたように、TypeScriptで拡張された大きな機能はクラス定義にまつわる部分と、静的な型指定(型注釈)が可能になった点である。
class Program { // クラス定義
constructor() {} // コンストラクターの名前は「constructor」
static Main():void { // 静的メソッドの定義。戻り値はvoid
console.log("hello from Program.Main");
}
}
Program.Main();
C#プログラマーにもすっきりと分かりやすいはずだ。気になるのは「static Main():void」という部分くらいだろう。「static」はC#の「static」と同じでこれがC#でいうところの静的メソッド(クラスメソッド)であることを意味する。また、「:void」という部分は「型注釈」と呼ばれるもので、この場合はMainメソッドの戻り値の型が「void」であることを示す。つまり、C#で「static void Main」と記述したのと同等ということだ。その他にはコンストラクターの名前が「constructor」となっていることは覚えておこう。
なお、TypeScriptでは型注釈がサポートされているが、ECMAScript 2015にはこれは含まれていない。次世代のECMAScript仕様であるES7では、これがサポートされる予定だ。
次にECMAScript 2015におけるクラス定義を見てみよう。
class Program { // クラス定義
constructor() {} // コンストラクターは「constructor」
static Main() { // 静的メソッドの定義。型注釈はない
console.log("hello from Program.Main");
}
}
Program.Main();
型注釈がECMAScript 2015にはない点を除けばTypeScriptと同様だ。特に説明を追加する必要はないだろう。
以上で最初に見たC#プログラムがJavaScript 5/TypeScript/ECMAScript 2015でどうなるかが分かったはずだ。TypeScript/ECMAScript 2015では、C#プログラマーにとって直感的に理解しやすいコードが書ける。ただし、このプログラムはあまりにもシンプルだったので、次にインスタンス変数やインスタンスメソッドを持ったクラスをどう記述するかを見てみよう。
Copyright© Digital Advantage Corp. All Rights Reserved.