「何かをひとまとめにする」ためにクラスを使う
今までご紹介した記事では,カスタム・クラスを使用する際には,new演算子を使用してインスタンスを生成し,それを利用してきました。インスタンスを生成するということは「メモリー上で,インスタンス変数を書き込む場所を確保する」ことでしたね。カスタム・クラスには,上記の方法とは別に,new演算子でインスタンスを作成しなくても使用することのできる「クラス・プロパティ」「クラス・メソッド」という仕組みが用意されています。この仕組みを使うと,すっきりと情報をまとめることができます(図1)。
図1: クラス・プロパティのイメージ(クリックするとムービーを表示します)
クラスを使って,「わかりにくくて散らかりやすいもの」を「わかりやすく整理する」わけですね(*1)。
西暦を和暦に変換するクラスを作成してみよう
日本に住んでいる皆さんは,「2007年」のような西暦を「明治・大正・昭和・平成○○年」といった和暦に変換する機会があるかと思います。西暦から和暦を求めるには,表1のような数値を西暦の数値から減算すればOKです。
元号 | 減算する数値 |
---|---|
明治 | 1867 |
大正 | 1911 |
昭和 | 1925 |
平成 | 1988 |
例えば,「2007年」を「平成」に変換するならば,「2007」から「1988」を引いて「19」。「平成19年」となるわけです。でも,この計算,咄嗟にできますか? 急に言われると,なかなか数字がでてこないですよね。
さらには元号が切り替わる年や日付なども考え出すと,もうお手上げです(表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」という形式で記述するために,見た目にも「ああ,和暦にコンバートしてるんだなあ」と,処理の内容が直観的にわかりやすくなりますね。