# ⑦列挙型Enumについて ## 列挙型Enum カードのスートのように、特定の種類以外は存在しえないような概念 そういったものを定義するのが列挙型Enumです(以下Enum) 実例を挙げるとすると、注文の状態などでしょうか 「支払待」「在庫不足」「発送可能」「発送済」「配送完了」 我々も注文をした後に発送状況など確認すると思いますが おそらくそこの表記も、Enumと似た概念で実装されているはずです 発送状況:「盆踊り中」とか適当な状態書かれてたらウケますね ### 記述例と構文説明 #### Enumの定義 ``` public enum SeasonEnum { SPRING, SUMMER, AUTUMN, WINTER; } ``` 上記は四季をEnumとして記述した例です 四季も、日本では春夏秋冬の4つしかありませんよね Enumを定義するときは、クラスを定義するときと同様javaファイルを作ります そのうえで、クラスであれば「public class クラス名」となるところを 「public enum Enum名」としてあげます 中身は、Enumで定義したい要素をカンマ区切りで列挙します 全部大文字なのは慣習です 慣習ついでに... 上の記述例では要素を横一列に並べていますが (カンマ区切り・行末の;の必要性を強調しています) 過去に僕がいた案件では、下記のように縦に並べる様に列挙してました ``` public enum SeasonEnum { SPRING, SUMMER, AUTUMN, WINTER; } ``` #### Enumの宣言 ``` SeasonEnum season = SeasonEnum.SPRING; ``` Enum型の変数を宣言するときは、上記のようにEnum名と要素をつなぎます メソッド呼び出しの時に使っている、ドット演算子の考え方と同じです 要は「SeasonEnumという列挙型のなかのSPRINGという要素」と言う意味です つぎに、宣言したEnumを出力してみるとどうなるのでしょうか ``` System.out.pringln(season) ``` ![image](../Images/02_07_01.png) このように、定義したEnumの要素がそのまま表示されます 当たり前っちゃ当たり前...な気がしますね それでは... 「画面に出力する文字列は日本語がいい」 と言われたらどのように実装しましょうか Enumの要素名を日本語にする...は、ちょっとナシにしましょう (できるけど) Enumの要素名はそのままに、表示名を変える それを実現させるために、次の記述を加えます #### Enumの各要素に属性を持たせる ``` public enum SeasonEnum { SPRING("春"), SUMMER("夏"), AUTUMN("秋"), WINTER("冬"); String jpnName; private SeasonEnum(String jpnName) { this.jpnName = jpnName; } public String getJpnName() { return this.jpnName; } } ``` 急にドカッと記述が増えました 頭が痛くなってきたかもしれませんが、少しだけ辛抱を もしかしたら、ところどころ知っている概念があるかもしれません まず、Enumの各要素の後ろに()がついて、中に日本語名が入っています そして、Enumの要素とは別にjpnNameなる変数が増えていて... なんかメソッドも新しく2つ作られています わかりやすいところからいきましょう jpnNameという変数が急に生まれたことを仮に受け入れるとして した二つのメソッドは、コンストラクタと、アクセサ(ゲッター) に見えませんか? 見えませんか?というか、ズバリそのものなんですが ``` public enum SeasonEnum { SPRING("春"), SUMMER("夏"), AUTUMN("秋"), WINTER("冬"); String jpnName; // コンストラクタ // ただし、可視性はprivate private SeasonEnum(String jpnName) { this.jpnName = jpnName; } // ゲッター public String getJpnName() { return this.jpnName; } } ``` 変数が生まれた意味は置いておいて... 「属性を持たせたくなったら、コンストラクタとゲッターは実装する!」 そういう決め事と一旦とらえておきましょう。 そして、決め事ついでに、「Enumのコンストラクタの可視性はprivate」です さて、残った謎は「jpnName」なる変数が生まれた理由です そもそも、今の変更を加えることになった理由は 「英名ではなく和名表示をしたい」からでした つまり... SPRINGに、自身の名前(英)のほかに”春”という名前(和)を持たせたい SUMMERに、自身の名前(英)のほかに”夏”という名前(和)を持たせたい AUTUMNに、自身の名前(英)のほかに”秋”という名前(和)を持たせたい WINTERに、自身の名前(英)のほかに”冬”という名前(和)を持たせたい ということです ところで、これらの”春”,”夏”,”秋”,”冬”は、データ型で表すとしたらなんでしょう そして、jpnNameは何型で定義されているでしょうか なんとなーく、わかってきた気がしませんか ここで、情報を増やしてみましょう 「春夏秋冬に1-4の順番を持たせたい」 こうした場合、どういう記述に変わるでしょうか ``` public enum SeasonEnum { SPRING("春", 1), ......① SUMMER("夏", 2), AUTUMN("秋", 3), WINTER("冬", 4); String jpnName; ......② int number; // コンストラクタ ......③ private SeasonEnum(String jpnName, int number) { this.jpnName = jpnName; this.number = number; } /* アクセサは記載省略 */ ......④ } ``` このようになります つまり、Enumの各要素に情報を付け足したくなった場合は * ①Enumの各要素の後ろに()をつけて、与えたい情報を記載する * ②与えた情報と同じ型の変数を属性として定義する * ③定義した変数を持つ引数有コンストラクタを定義する * ただし可視性はprivate * ④必要に応じて変数のアクセサを用意する 長かったですね...... Enumは慣れてしまえば使いやすいものの、ハードルの高い概念だと思います 一度ですべて覚えきろうとせず、逐一戻りながら実装してみましょう 何度も言いますが、勉強会中であれば聞いてもらって構いません ## 課題5 Enumでスートを定義する * ①Enumでスートを定義してみましょう * Enum名:SuitEnum * 各スートの英字表記 * SPADE * HEART * DIA * CLUB * ②Enumの各要素に、和名の属性を追加しましょう * スペード * ハート * ダイヤ * クラブ * ③いずれかのEnumを変数として宣言し、和名で出力させてみましょう