〜列挙型〜
【注意】この章はJava5.0の新機能についての解説です。
13章の継承の解説で保育園児を登場させました。ちょっと保育園児のクラスは不自然でしたが、ポリモーフィズムまで一気に進めるために、勘弁してもらいました。やはり保育園児のクラスは、氏名と組(青、黄、桃)をインスタンス変数として持つのが自然ですよね。
入園式で最初にもらった桃色の名札(桃組ですから)、ひらがなで名前が書いてありした。他にも血液型や保護者の名前や住所が入ってましたが、わけがわからなくなるので、ここではカット。今回はその組にスポットを当てます。
保育園児のクラスはこんな感じになりました。インスタンス変数kumiは、文字列AOかKIかMOMOが入ります。メソッドtonjiruは、組によってやることを分けています。メソッドtoStringでは、組の名前を漢字にして、名前とつなげて文字列にしています。
public class Hoikuenji { |
さて保育園児を3人用意して、豚汁の準備をさせましょう。
public class Main { public
static void main(String[] args) { |
出力はこうなりました。ここまでは大丈夫ですか?今までの復習です。
青組 太郎
野菜を切る
黄組 次郎
野菜の皮をむく
桃組 三郎
野菜を洗う
では質問です。もしクラスMainのx[0]の代入のところで、こうしたら何が出力されるでしょうか?
x[0] = new Hoikuenji(“太郎”, “AI”);
次のよう出力されます。
組 太郎
黄組 次郎
野菜の皮をむく
桃組 三郎
野菜を洗う
クラスHoikuenjiでは、AIという組は想定していません。そこでメソッドtoStringではstが空文字のままなので、組の名前が出ません。またメソッドtonjiruでは何も出力されません。ちょっとした入力ミスで、太郎くんは幽霊保育園児になってしまいました。それでも気がついた人がいて「あらあら太郎くんはどの組かしら、豚汁のときは何もやらないのかしら?」といってくれればいいほうです。かわいそうな太郎くんです。
もともとクラスHoikuenjiのインスタンス変数kumiの型がStringであるため、コンストラクタでどんな文字列でも受け取れてしまうことに原因があるのです。ではどうすればよいでしょうか?
インスタンス変数kumiの型を、Stringから、AO、KI、MOMOの三つの組しか受け付けないような、特別な型に変更すれば良いですね。つまり三つの定数のみを表す型があればいいわけです。こんなときは列挙型です。次のように定義します。
public enum Kumi { |
型の名前はKumi、三つの定数、これを列挙定数といいますが、AO、KI、MOMOが定義されています。クラスの定義とどこが違うかというと、「class」が「enum」、そしてすぐ列挙定数を列挙するところです。列挙型は、クラス型の仲間ですが、書き方は全然違いますね。
プログラム中に実際指定することはありませんが、実はこれらの列挙定数はどれも「public」で「static」で「final」です。これらの意味はいいですね。他のクラスで列挙定数を使うときは、列挙型名とともにKumi.AO、Kumi.KI、Kumi.MOMOのように指定します。staticの変数はクラス変数で頭にクラス名を付けて呼びました。列挙型も同じです。
さてkumiの型はこの列挙型のKumiにします。
private Kumi kumi;
そうすると、変数kumiに代入できるのは、Kumi.AOかKumi.KIかKumi.MOMOのどれかになります。それ以外は代入できません。
kumi = Kumi.AO; OKです。
kumi = “AO”; 文字列はString型なので代入できません。
kumi = Kumi.AI; 列挙型KumiにAIという列挙定数はないので、エラーになります。
では先ほどのクラスHoikuenjiの前半部分を書き換えてみましょう。
public class Hoikuenji { public
Hoikuenji(String name, Kumi kumi) { |
太字が書き換えた部分です。kumiの型をKumiに変更しただけです。でもこれによって、このコンストラクタを呼び出すのに、二番目の引数には、
Kumi.AO Kumi.KI Kumi.MOMO
のどれか以外は指定できなくなります。上の代入と同じです。幽霊保育園児を作らなくてすみます。
では後半のメソッド二つも書き換えましょう。switch文の( )内は、結果がchar、byte、short、intのどれかになる式でなければならないのですが、それに加え列挙型もOKになりました。つまり変数kumiを指定できるわけです。メソッドtonjiruは次のようになります。
public void tonjiru() { switch (kumi) { |
kumiの値がAOであれば、「野菜を切る」と出力されます。KIであれば「野菜の皮をむく」、MOMOであれば「野菜を洗う」ですね。おやおやcaseのところの列挙定数に、Kumi.AOのように列挙型名Kumiがついてないですね。switch文のcaseで指定する列挙定数についてのみ、列挙型名はつけてはいけないことになっています。そのかわり、importでKumiの場所を教えておいてやる必要はあります。(あるいはフルネームを指定するか)これは普通のクラスと同じですね。もし列挙型Kumiがパッケージp2に、クラスHoikuenji がパッケージp1にあるのであれば、Hoikuenjiの最初はこうなります。
package p1; |
上のメソッドtonjiruをif文で書き換えると次のようになります。列挙定数には列挙型名が必要です。
public void
tonjiru() { |
もしこのいくつも出てくる「Kumi」をなくしたければ、そう、20章の追加でやった「import static」の出番です。列挙定数はすべてstaticなので、列挙定数から頭に載せた重い列挙型名を、すべて取り除くことができます。
import p2.Kumi; |
メソッドtoStringは次のようになりました。
public String toString() { |
public enum Kumi { |
[クラスHoikuenji]
public class Hoikuenji { |
[クラスMain]
public class Main { |