PR
 クラスの仕組みを利用すると,一目で何に使うのかわかりにくいような値や,将来的に変更があるかもしれないような値を,見た目にわかりやすい定数として管理することができます。また,よく使う定番の処理を「クラス・メソッド」として扱うこともできます。

「何かをひとまとめにする」ためにクラスを使う

 今までご紹介した記事では,カスタム・クラスを使用する際には,new演算子を使用してインスタンスを生成し,それを利用してきました。インスタンスを生成するということは「メモリー上で,インスタンス変数を書き込む場所を確保する」ことでしたね。

 カスタム・クラスには,上記の方法とは別に,new演算子でインスタンスを作成しなくても使用することのできる「クラス・プロパティ」「クラス・メソッド」という仕組みが用意されています。この仕組みを使うと,すっきりと情報をまとめることができます(図1)。

図1: クラス・プロパティのイメージ(クリックするとムービーを表示します)

 クラスを使って,「わかりにくくて散らかりやすいもの」を「わかりやすく整理する」わけですね(*1)。

西暦を和暦に変換するクラスを作成してみよう

 日本に住んでいる皆さんは,「2007年」のような西暦を「明治・大正・昭和・平成○○年」といった和暦に変換する機会があるかと思います。西暦から和暦を求めるには,表1のような数値を西暦の数値から減算すればOKです。

表1: 西暦から和暦を計算する時の数値
元号減算する数値
明治1867
大正1911
昭和1925
平成1988

 例えば,「2007年」を「平成」に変換するならば,「2007」から「1988」を引いて「19」。「平成19年」となるわけです。でも,この計算,咄嗟にできますか? 急に言われると,なかなか数字がでてこないですよね。

 さらには元号が切り替わる年や日付なども考え出すと,もうお手上げです(表2)(*2)。

表2: それぞれの元号の年代
元号西暦での年代
明治1868/1/25~1912/7/30
大正1912/7/30~1926/12/25
昭和1926/12/25~1989/1/7
平成1989/1/8~

 こういう計算は西暦と和暦を変換するプログラムを作ってしまい,そこに任せるのが後々楽になりそうですね。いろいろなコードの書き方があるかとは思いますが,筆者は次のようにコードを記述してみました。

//元号を表す文字列を配列で管理する
var gengouString:Array = ["明治","大正","昭和","平成"];
//元号の計算に使用する数値を配列で管理する
var gengouNumber:Array = [1867,1911,1925,1988];
//どの元号なのかは,数値で管理するルールとする。
//0:明治 1:大正 2:昭和 3:平成

 基本的な方針は,四つの元号に対する元号名と,計算の際に使う数値を配列に入れて管理し,どの元号の計算を行うか,などの判断は,配列のインデックス番号で管理するというものです。こうしておけば「明治」で計算をしたい場合には,インデックス番号「0」の配列の値を取り出すと,それぞれ「明治」「1867」と必要な文字列と数値が取り出せます。

 さらに,この配列とインデックス番号のルールを使って,西暦から指定した元号での和暦の文字列を求める関数「convert」を追加します。

//一つ目の引数として受け取った日付を,
//二つ目の引数で指定した和暦として返す関数
function convert(_day:Date,_index:Number){
  //2番目の引数の値に応じた文字列や数値を配列から取り出して計算
  var _g:String = gengouString[_index] + 
      String(_day.getFullYear()-gengouNumber[_index]) + "年";
  var _m:String = String(_day.getMonth() + 1) + "月";
  var _d:String = String(_day.getDate()) + "日";
  return _g + _m + _d;
}

 この関数を使って「2007年7月13日」を「平成」形式で変換した結果を表示してみましょう。

//「2007年7月13日」を「平成」形式で変換
trace("変換結果は、" + convert(new Date(2007,6,13),3));

 Dateクラスを使用して任意の日付情報を作成する際には,「new Date(年,月,日)」とコードを記述します。この際,「月」の情報は,「1月」を「0」として指定しますのでご注意を。今回の用に「7月」を指定したい場合には,「6」と,実際の月の数字よりも一つ減算した値を指定してあげればOKというわけですね。

 さて,このコードの実行結果はというと,図2のようになります。きちんと和暦に変換されていますね。

図2: 西暦が和暦に変換された

 さて,基本的な変換ができることが確認できましたので,この処理を使いまわせるようにクラス化してみたいと思います。クラス名は,そうですね,そのまんま「Wareki」としてみます(図3)。

図3: 和暦への変換処理を管理する「Wareki」クラスを作成する

 先ほどの処理をまとめると,Warekiクラスのコードは次のようになります。

//和暦に関する情報をまとめたクラス
class Wareki {
 //一つ目の引数の日付を,二つ目の引数の値に応じた元号で変換する関数
 function convert(_day:Date,_index:Number):String{
  //元号を表す文字列を配列で管理する
  var gengouString:Array = ["明治","大正","昭和","平成"];
  //元号の計算に使用する数値を配列で管理する
  var gengouNumber:Array = [1867,1911,1925,1988];
  //どの元号なのかは,数値で管理するルールとする。
  //0:明治 1:大正 2:昭和 3:平成
  //2番目の引数の値に応じた文字列や数値を配列から取り出して計算
  var _g:String = gengouString[_index] + 
      String(_day.getFullYear()-gengouNumber[_index]) + "年";
  var _m:String = String(_day.getMonth() + 1) + "月";
  var _d:String = String(_day.getDate()) + "日";
  return _g + _m + _d;
 }
}

 Warekiクラスを,「convertメソッド」のみを持つクラスとして定義できました。でもちょっと待ってください。このままでは,Warekiクラスのconvertメソッドを利用するには,以下のようにnew演算子を使ってインスタンスを生成しなくてはいけません。

//convertメソッドを使用したいので,Warekiクラスのインスタンスを生成
var _w:Wareki = new Wareki();
//2007年7月13日を「平成」形式で変換
var _day:Date = new Date(2007,6,13);
trace("変換結果は," + _w.convert(_day,3));

 単に変換したいだけなのに,なんだかひと手間多い様な気がしますよね。そういえば,計算をするMathクラス等のメソッドは,「Math.random()」や「Math.floor()」のように,いちいちnew演算子でインスタンスを生成しなくても使えます。Warekiクラスでも,インスタンスを生成せずにconvertメソッドを使用したいものです。

 このようなケースでは,「staticステートメント」を使用するのが効果的です。使用方法は簡単。インスタンスを生成しなくても使用したいメソッド名の先頭に「static」と付け加えるだけです(図4)。

図4: staticステートメントを付け加える

 staticステートメントを使って宣言されたメソッドは,「クラス・メソッド」もしくは,「静的メソッド」と呼ばれるメソッドとして認識されるようになります。クラス・メソッドは,前述の「Math.randomメソッド」のように,「クラス名.クラス・メソッド(引数)」と記述するだけで,実行できるメソッドです(*3)。

 convertメソッドも,staticステートメントを加えたため,「Wareki.convert(引数)」と記述するだけで,和暦への変換ができるようになりました。

//2007年7月13日を「平成」形式で変換
var _day:Date = new Date(2007,6,13);
//Warekiクラスのクラス・メソッド「convert」を利用して変換
trace("変換結果は、" + Wareki.convert(_day,3));

 「Wareki.convert」という形式で記述するために,見た目にも「ああ,和暦にコンバートしてるんだなあ」と,処理の内容が直観的にわかりやすくなりますね。