リテラルそのものの話からは若干外れるが、最後にTypeScriptのとても便利なデータ型である列挙型(enum)型を紹介しておこう。「enum」とは「enumurate」の略で、文字通り「列挙する」という意味だ。例から見てみよう。ちょっと長くなるがPlaygroundで以下のコードを入力して、実行しよう。
コードを見ただけでも何となく意味が分かると思うが、1行目では「SPRING」「SUMMER」「AUTUMN」「WINTER」の4つの季節に「SEASONS」という分かりやすい名前を付けている。「enum」というキーワードの後に好きな名前を指定し、「{}」の中に要素を書けばいい。別に大文字で書かないといけないわけではないが、通常の変数やリテラルと区別できるように、ここではわざと大文字で書いてある。
このように定義しておくと「名前.要素名」という書き方で、それぞれの要素が利用できる。プログラムを実行してみると「2」という結果が表示されるはずだ。Playgroundの右側に表示されたJavaScriptのコードは以下のようになっている。
var SEASONS;
(function (SEASONS) {
SEASONS[SEASONS["SPRING"] = 0] = "SPRING";
SEASONS[SEASONS["SUMMER"] = 1] = "SUMMER";
SEASONS[SEASONS["AUTUMN"] = 2] = "AUTUMN";
SEASONS[SEASONS["WINTER"] = 3] = "WINTER";
})(SEASONS || (SEASONS = {}));
;
alert(2 /* AUTUMN */);
あまりにも複雑なコードなので、今の段階では何が何だか分からないかもしれないが、実際にはSEASONS.SPRINGには0が、SEASONS.SUMMERには1が、SEASONS.AUTUMNには2が、SEASONS.WINTERには3が入れられていることが確認できる。
わざわざこういう回りくどいことをしないで、「season = 2;」のように書けばいいじゃないかと思われるかもしれないが、これでは、変数の値が2であることは分かっても、季節が秋であることが分からない。
列挙型を使うと、いくつかの種類に分けられるものに意味のある名前を与えられるというわけだ。
さて、列挙型の名前は変数の宣言にも使える。というより、変数を宣言してこそ意味がある。書き方は、以下のようになる。
var season:SEASONS
変数の宣言では「:」で区切ってデータ型を書くわけだが、データ型としてenum型の名前を指定すればよい。
このように書くと、SEASONSのいずれかの値だけを代入するのに使う変数seasonが作られる。実際には他の値も代入できるのだが、この変数が、SEASONSのいずれかの値しか取らないということがよく分かるようになる。
以下のコードで、実際に試してみよう。
enum SEASONS{SPRING, SUMMER, AUTUMN, WINTER};
var season:SEASONS; // (1)
season = SEASONS.SUMMER; // (2)
// (3)
if(season == SEASONS.SUMMER){
alert("夏ですね");
} else {
alert("夏ではないですね");
}
(1)がSEASONSのいずれかの値を取るseasonという変数の宣言だ。(2)で、seasonsにSEASONS.SUMMERを代入しているので、季節は夏であることが分かる。(3)以降では、seasonsの値によって異なるメッセージを表示する。
列挙型を定義するということは、いくつかの種類に分けられるような新しいデータ型を作ることと考えてもいいだろう。つまり、以下のように書くことにより、SPRING、SUMMER, AUTUMN, WINTERという4つの値だけを表せるSEASON型という新しいデータ型が作られた、というわけだ。
enum SEASONS{SPRING, SUMMER, AUTUMN, WINTER};
変数の宣言は、以下のような形式だったことを思いだそう。
var 変数名:データ型;
そして列挙型の変数の宣言はちゃんとその形式になっている。
var season:SEASONS;
なお、列挙型の定義では、それぞれの要素に与える整数値を指定しておくこともできる。例えば、以下のように書くと、「SPRING」の実際の値が「1」となる。その後は連番になるので「SUMMER」は「2」、「AUTUMN」は「3」、「WINTER」は「4」となる。
enum SEASONS{SPRING=1, SUMMER, AUTUMN, WINTER};
また、全ての要素に個別の値を指定することもできる。単に種類を区別するだけなら、値を指定する必要はないが、種類が組み合わされる場合には値の指定が便利になる。例えば、以下のようなプログラムが書ける(結果は「春夏物です」となる)。
enum SEASONS{SPRING=1, SUMMER=2, AUTUMN=4, WINTER=8}; // (1)
var season:SEASONS;
season = SEASONS.SPRING + SEASONS.SUMMER; // (2)
// (3)
switch(season){
case SEASONS.SPRING:
alert("春物です");
break;
case SEASONS.SPRING + SEASONS.SUMMER:
alert("春夏物です");
break;
default:
alert("秋または冬にも使えます");
}
(1)の定義のようにそれぞれの要素に2のべき乗の値を与えておくと、以下のように、全ての組み合わせを異なる値にできる。
要素の組み合わせ | 得られる値 |
---|---|
SEASON.SPRING | 1 |
SEASON.SUMMER | 2 |
SEASON.SPRING + SEASON.SUMMER | 3 |
SEASON.AUTUMN | 4 |
SEASON.SPRING + SEASON.AUTUMN | 5 |
SEASON.SUMMER + SEASON.AUTUMN | 6 |
SEASON.SPRING + SEASON.SUMMER + SEASON.AUTOMN | 7 |
SEASON.WINTER | 8 |
SEASON.SPRING + SEASON.WINTER | 9 |
SEASON.SUMMER + SEASON.WINTER | 10 |
SEASON.SPRING + SEASON.SUMMER + SEASON.WINTER | 11 |
SEASON.AUTUMN + SEASON.WINTER | 12 |
SEASON.SPRING + SEASON.AUTOMN + SEASON.WINTER | 13 |
SEASON.SUMMER + SEASON.AUTOMN + SEASON.WINTER | 14 |
SEASON.SPRING + SEASON.SUMMER + SEASON.AUTOMN + SEASON.WINTER | 15 |
季節の全ての組み合わせに異なる値を与える |
上のサンプルコードの(2)では、seasons変数にSEASONS.SPRING + SEASONS.SUMMERを代入している。実際の値は1+2なので3になることが分かる。(3)以降のswitch文については回を改めて詳しく説明するが、season変数の値によって処理をいくつかに分けるためのコードだ。この場合は、8行目の「case SEASONS.SPRING + SEASONS.SUMMER:」に一致したので、その下に書かれているalertメソッドが実行され「春夏物です」というメッセージが表示された。
なお、このような値の組み合わせを取り扱いたい場合には、実際には「|」(bitごとの論理和)や「&」(bitごとの論理積)という演算子を使った方がいい。例えば、8行目は以下のように書ける。
case SEASONS.SPRING | SEASONS.SUMMER:
bit演算では符号付きの32bit値が使われるが、下位4bitだけで見てみると、以下のようになる。
値 | 10進数 | 2進数 | 備考 |
---|---|---|---|
SEASONS.SPRING | 1 | 0001 | |
SEASONS.SUMMER | 2 | 0010 | |
SEASONS.SPRING + SEASONS.SUMMER | 3 | 0011 | 通常の加算 |
SEASONS.SPRING | SEASONS.SUMMER | 3 | 0011 | bitごとの論理和(OR) |
SEASONS.SPRING & SEASONS.SUMMER | 0 | 0000 | bitごとの論理積(AND) |
bitごとの論理演算の例 |
bitごとの論理和では、2進数で表された2つの値の各桁を比較して、どちらかが1であれば、結果の値の対応する桁も1になる。0および正の整数同士の計算であれば「+」でも「|」でも同じ結果になるのだが「|」演算子を使った方が、bitごとに値を調べていることが分かりやすい(論理演算に使うことはあまりないが、負の値や浮動小数点数の場合「+」と「|」の結果は異なる)。
ちなみに、bitごとの論理積では、2つの2進数の各桁の両方が1のときだけ、結果の桁も1となる。bit演算は組み合わせを調べたり、設定したりするのに便利だが、だいぶ話がそれてしまったので、また機会を改めて見ることとしよう。
今回はTypeScriptにおけるリテラルの種類と列挙型を紹介した。演算子や条件分岐などについても少し先走った話をしたが、予告編としてでも捉えておいてもらうといいだろう。というわけで、次回からは演算子について詳しく見ていくこととする。
Copyright© Digital Advantage Corp. All Rights Reserved.