<<前ページ目次次ページ>>

〜列挙型〜

【注意】この章はJava5.0の新機能についての解説です。

 

 13章の継承の解説で保育園児を登場させました。ちょっと保育園児のクラスは不自然でしたが、ポリモーフィズムまで一気に進めるために、勘弁してもらいました。やはり保育園児のクラスは、氏名と組(青、黄、桃)をインスタンス変数として持つのが自然ですよね。


保育園児のバッジ

 入園式で最初にもらった桃色の名札(桃組ですから)、ひらがなで名前が書いてありした。他にも血液型や保護者の名前や住所が入ってましたが、わけがわからなくなるので、ここではカット。今回はその組にスポットを当てます。

 保育園児のクラスはこんな感じになりました。インスタンス変数kumiは、文字列AOKIMOMOが入ります。メソッドtonjiruは、組によってやることを分けています。メソッドtoStringでは、組の名前を漢字にして、名前とつなげて文字列にしています。

public class Hoikuenji {
        private String name;
        private String kumi;
       
        public Hoikuenji(String name, String kumi) {
                this.name = name;
                this.kumi = kumi;
        }

        public void tonjiru() {
                if(kumi.equals("AO")) {
                        System.out.println("野菜を切る");
                } else if(kumi.equals("KI")) {
                        System.out.println("野菜の皮をむく");
                } else if(kumi.equals("MOMO")) {
                        System.out.println("野菜を洗う");
                }
        }
               
        public String toString() {
                String st = null;
                if(kumi.equals("AO")) {
                        st = "";
                } else if(kumi.equals("KI")) {
                        st = "";
                } else if(kumi.equals("MOMO")) {
                        st = "";
                }
                return st + " " + name;
        }
}

 さて保育園児を3人用意して、豚汁の準備をさせましょう。

public class Main {

              public static void main(String[] args) {
                            Hoikuenji[] x = new Hoikuenji[3];
                            x[0] = new Hoikuenji("太郎", "AO"); 
                     x[1] = new Hoikuenji("次郎", "KI");
             x[2] = new Hoikuenji("三郎", "MOMO");
                            for (int i = 0; i < x.length; i++) {
                                       
System.out.println(x[i]);

                                        
x[i].tonjiru();

                            }
              }
}

 出力はこうなりました。ここまでは大丈夫ですか?今までの復習です。

青組 太郎
野菜を切る
黄組 次郎
野菜の皮をむく
桃組 三郎
野菜を洗う



幽霊!?

 では質問です。もしクラスMainのx[0]の代入のところで、こうしたら何が出力されるでしょうか?

   x[0] = new Hoikuenji(“太郎”, “AI”);

次のよう出力されます。
太郎
黄組 次郎
野菜の皮をむく
桃組 三郎
野菜を洗う

 クラスHoikuenjiでは、AIという組は想定していません。そこでメソッドtoStringではst空文字のままなので、組の名前が出ません。またメソッドtonjiruでは何も出力されません。ちょっとした入力ミスで、太郎くんは幽霊保育園児になってしまいました。それでも気がついた人がいて「あらあら太郎くんはどの組かしら、豚汁のときは何もやらないのかしら?」といってくれればいいほうです。かわいそうな太郎くんです。

 もともとクラスHoikuenjiのインスタンス変数kumiの型がStringであるため、コンストラクタでどんな文字列でも受け取れてしまうことに原因があるのです。ではどうすればよいでしょうか?


青黄桃だけ

 インスタンス変数kumiの型を、Stringから、AOKIMOMOの三つの組しか受け付けないような、特別な型に変更すれば良いですね。つまり三つの定数のみを表す型があればいいわけです。こんなときは列挙型です。次のように定義します。

public enum Kumi {
              AO, KI, MOMO
}


 型の名前はKumi、三つの定数、これを列挙定数といいますが、AOKIMOMOが定義されています。クラスの定義とどこが違うかというと、「class」が「enum」、そしてすぐ列挙定数を列挙するところです。列挙型は、クラス型の仲間ですが、書き方は全然違いますね。

 プログラム中に実際指定することはありませんが、実はこれらの列挙定数はどれも「public」で「static」で「final」です。これらの意味はいいですね。他のクラスで列挙定数を使うときは、列挙型名とともにKumi.AOKumi.KIKumi.MOMOのように指定します。staticの変数はクラス変数で頭にクラス名を付けて呼びました。列挙型も同じです。

さてkumiの型はこの列挙型のKumiにします。

 private Kumi kumi;

 そうすると、変数kumiに代入できるのは、Kumi.AOKumi.KIKumi.MOMOのどれかになります。それ以外は代入できません。

 kumi = Kumi.AO;    OKです。
  kumi = “AO”;   文字列はString型なので代入できません。
  kumi = Kumi.AI;   列挙型KumiAIという列挙定数はないので、エラーになります。

 では先ほどのクラスHoikuenjiの前半部分を書き換えてみましょう。

public class Hoikuenji {
              private String name;
              private Kumi kumi;                            

              public Hoikuenji(String name, Kumi kumi) { 
                            this.name = name;
                            this.kumi = kumi;
              }
            :


 太字が書き換えた部分です。kumiの型をKumiに変更しただけです。でもこれによって、このコンストラクタを呼び出すのに、二番目の引数には、
   Kumi.AO   Kumi.KI   Kumi.MOMO
のどれか以外は指定できなくなります。上の代入と同じです。幽霊保育園児を作らなくてすみます。



Kumiが付いたり付かなかったり

 では後半のメソッド二つも書き換えましょう。switch文の( )内は、結果がcharbyteshortintのどれかになる式でなければならないのですが、それに加え列挙型もOKになりました。つまり変数kumiを指定できるわけです。メソッドtonjiruは次のようになります。

    

      public void tonjiru() {

                            switch (kumi) {
                      case AO:
                                  System.out.println("野菜を切る");
                                  break;
                      case KI:
                                  System.out.println("野菜の皮をむく");
                                  break;
                      case MOMO:
                                  System.out.println("野菜を洗う");
                                  break;
                      default:
                                  System.out.println("?");
                      }
              }

   kumiの値がAOであれば、「野菜を切る」と出力されます。KIであれば「野菜の皮をむく」、MOMOであれば「野菜を洗う」ですね。おやおやcaseのところの列挙定数に、Kumi.AOのように列挙型名Kumiがついてないですね。switch文のcaseで指定する列挙定数についてのみ、列挙型名はつけてはいけないことになっています。そのかわり、importKumiの場所を教えておいてやる必要はあります。(あるいはフルネームを指定するか)これは普通のクラスと同じですね。もし列挙型Kumiがパッケージp2に、クラスHoikuenji がパッケージp1にあるのであれば、Hoikuenjiの最初はこうなります。

package p1;
import p2.Kumi;
public class Hoikuenji {

 上のメソッドtonjiruif文で書き換えると次のようになります。列挙定数には列挙型名が必要です。

    public void tonjiru() {
                if(kumi == Kumi.AO) {          
                        System.out.println("野菜を切る");
                } else if(kumi == Kumi.KI) {
                        System.out.println("野菜の皮をむく");
                } else if(kumi == Kumi.MOMO) {
                        System.out.println("野菜を洗う");
                } else {
                        System.out.println("?");
                }
        }

もしこのいくつも出てくる「Kumi」をなくしたければ、そう、20章の追加でやった「import static」の出番です。列挙定数はすべてstaticなので、列挙定数から頭に載せた重い列挙型名を、すべて取り除くことができます。

import p2.Kumi;
import static p2.Kumi.AO;
import static p2.Kumi.KI;
import static p2.Kumi.MOMO;

public class Hoikuenji {
             
        public void tonjiru() {
                if(kumi == AO) {               
                        System.out.println("野菜を切る");
                } else if(kumi == KI) {
                        System.out.println("野菜の皮をむく");
                } else if(kumi == MOMO) {
                        System.out.println("野菜を洗う");
                } else {
                        System.out.println("?");
                }
        }

 メソッドtoStringは次のようになりました。

       public String toString() {
                           String st = "";
                           switch (kumi) {
                      case AO:
                                  st = "";
                                  break;
                      case KI:
                                  st = "";
                                  break;
                      case MOMO:
                                  st = "";
                                  break;
                      default:
                                  st = "?";
                      }
                          return st + " " + name;
              }

 

まとめてみましょ

 列挙型を使った例の全体をもう一度載せておきます。すべて同一パッケージにあるものとします。

 [列挙型Kumi]

public enum Kumi {
        AO, KI, MOMO
}


[クラスHoikuenji]

public class Hoikuenji {
  private String name;
  private Kumi kumi;

  public Hoikuenji(String name, Kumi kumi) {
    this.name = name;
    this.kumi = kumi;
  }

  public void tonjiru() {
    switch (kumi) {
    case AO:
      System.out.println("野菜を切る");
      break;
    case KI:
      System.out.println("野菜の皮をむく");
      break;
    case MOMO:
      System.out.println("野菜を運ぶ");
      break;
    default:
      System.out.println("?");
    }
  }

  public String toString() {
    String st = "";

    switch (kumi) {
    case AO:
      st = "青";
      break;
    case KI:
      st = "黄";
      break;
    case MOMO:
      st = "桃";
      break;
    default:
      st = "?";
    }
    return st + "組 " + name;
  }
}


[クラスMain]

public class Main {
        public static void main(String[] args) {
                Hoikuenji[] x = new Hoikuenji[3];
                x[0] = new Hoikuenji("太郎", Kumi.AO); 
              x[1] = new Hoikuenji("次郎", Kumi.KI);     
                x[2] = new Hoikuenji("三郎", Kumi.MOMO);
               
                for (int i = 0; i < x.length; i++) {
                        System.out.println(x[i]);
                        x[i].tonjiru();
                }
        }
}

<<前ページ目次次ページ>>
Copyright (c) 2007 Nagi Imai All Rights Reserved.
22.組は三つ、青黄桃