はじめに
- 今回のお題は表題の通りです
きっかけ
- チーム開発をしていて、Enumにおける情報の持たせた方って結構人によってまちまちで、
ちょっと不満があったので記事にして鬱憤を晴らそうという今回の魂胆であります自分の知識整理に生かそうと思いました。
問題のコード
- さっそく本題に入っちゃおうかと思いますが、まず前提としてEnumの定数の名前って、基本的に大文字+アンスコってのは共通理解だと思います(Enumじゃなくても)
- そんで、下みたいな感じで書いていくと思うんですけど
WeatherEnum.java
public enum WeatherEnum {
WEATHER_SUNNY("weather_sunny", "sunny"),
WEATHER_CLOUDY("weather_cloudy", "cloudy")
;
private String lowerCase;
private String shortName;
// GetterとConstructorは省略
}
- 気になったのは、定数名の全小文字をEnumの情報として持つような実装をしてるケースがあって、それってどうなのかなと個人的にもやもやした次第なのです。
気になった理由
- 保守性をあまり考えてない気がした(定数名と値の両方を修正する必要がある)
- toString().toLowerCase()すればいいじゃんというツッコミ
それでどうしたかというと・・・
- 値としては持たずに、呼び出し側でtoLowerCase()するのがベターな気がしたので、その場はそうする方向で倒したのですが、ちゃんと調べてみると色々できそうな気がしたので、ベストかはわからないけど、何個かアンサーを出して置こうかなと思います(多分、チーム内で合意が取れてればいいと思う)
案1
- 呼び出し元で毎回.toLowerCase()する
- これは多分、一番簡単なやり方な気がします。ただ、呼び元のコードが冗長になる気もします。
案2
- Enum側でメソッドを定義してしまう
- ほぼGetterみたいなメソッドを新たに定義するって感じです。
- 個人的にはあんまり好きじゃないです
WeatherEnum.java
public enum WeatherEnum {
WEATHER_SUNNY("sunny"),
WEATHER_CLOUDY("cloudy")
;
private String shortName;
// GetterとConstructorは省略
public String getLowerCase() {
return toString().toLowerCase();
}
}
案3
- toString()をオーバーライドする
- Enumの定数名の取り方ってname()かtoString()どちらかで取れると思うんですけど、name()がオーバーライドできなくて、toString()ができるって違いだと思うんですが、oracleDocsを読んだ感じ、定数名として定義したものより、もっとプログラマフレンドリなワードがある場合はtoStringをオーバーライドするといいよって書いてありますね。
- なので、全小文字の方がユースケース多いよって言うなら、オーバーライドしちゃって全然問題ないってことですね
- 個人的にはこれが本来の正しい使い方なのかと
WeatherEnum.java
public enum WeatherEnum {
WEATHER_SUNNY("sunny"),
WEATHER_CLOUDY("cloudy")
;
private String shortName;
// GetterとConstructorは省略
@Override
public String toString() {
return name().toLowerCase();
}
}
案4(おまけ)
- 結論としては、案3がいいのですがせっかく他にも思いついたので書くだけ書こうかと思います
- Java8からinterfaceに実装を持てるようになったので、interfaceで定義しておいて、EnumはimplementsしてOverRideするというやり方です
- 今回のような簡単なケースではメリットはなく、やりすぎ感は拭えないのですが、とはいえやり方の1つとして知っておいたもいいのかなと思います
HelloInterface.java
public interface HelloInterface {
String getLowerCase();
}
HelloEnum.java
public enum HelloEnum implements HelloInterface{
WEATHER_SUNNY( "sunny"),
WEATHER_CLOUDY( "cloudy")
;
private String shortName;
// GetterとConstructorは省略
@Override
public String getLowercase() {
return name().toLowerCase();
}
}
まとめ
- EnumのtoString()をオーバーライドして、自分たちのユースケース的に1番欲しい、定数名の表示形式を返すように実装してあげるのが良さそう
- その際に、全大文字が欲しいとかの稀なケースに出くわしたらname()で回避してあげようねって話でした