今まであまりEnumを使う機会はなかったのですが、ちょっと調べたらこれは見やすなって事でメモしておきます。Androidに限った話ではないですが、Androidっぽさも交えながらサンプルを作りました。サンプルの特徴としては、以下の3点です。
これを任意のメソッドの戻り値として利用することができます。こんな感じで
呼び出し元の戻り値ではgetErrorCodeでエラーコードを取得でき、getMessageでエラーメッセージを取得できます。エラーメッセージは、getMessageメソッドでstrings.xml経由で定義したIDから文字列に変換する工夫がしてあります。こうしておけば、多言語対応にも便利です。
switch文の判定には、前述の通り直接シンボル名で判定できます。下記サンプルは先ほどのエラーをswitch文で判定してメッセージ(Toast)の表示方法を分岐しています。ERROR_FORBIDDENの場合のメッセージはこんな感じで画面に
で、特徴の3つめですが、例えばEnumで定義したものをspinnerウィジェットへ表示させている場合、spinnerでは何番目が選択されかを返しますが、それがEnumで定義したどれに当たるか知りたい時があるかもしれません。その時に、Enumの定義をvalues()メソッドで配列として取得できるので、この配列の何番目かを見れば紐付けられます。
サンプルでは、spinnerウェジェットに表示されているいずれかのスイーツを選択すると、Toastに値段を表示するものです。
Enumの定義
spinner側の処理
onItemSelectedはspinnerの項目が選択されたタイミングで実行されます。Sweetsのvalues()で取得される配列とそのメソッドで渡されるpositionで紐付けてものをgetPriceをする事で値段の文字列を取得しています。
上記の全ソースはGithubへアップしました。
・takaiwa/EnumSample · GitHub
追記:2012/11/08
onItemSelected内のようなpositionが得られる場面でswitch文を使う場合
追記:2013/06/13
入れ子を表現
文字列で定義
switch文で定義
参考:Java enum- Cannot reference a field before it is defined - Stack Overflow
PR:オラクル認定資格教科書 Javaプログラマ Bronze SE 7 スピードマスター問題集 (EXAMPRESS)
PR:Java言語プログラミングレッスン 第3版(上)
- Enumの定義でswitch文を判定できる
- Enumの定義とstring.xmlのデータを紐付ける
- Enumの定義した順番で欲しい場合はvalues()メソッドで
特に何か意味のある実用的なサンプルではありませんが、上記特徴を表すために....
1は言わずと知れたことですが、それに加えてと2に関して。例えば以下のようなエラーコードとエラーのメッセージを取得できるように定義したとします。
1は言わずと知れたことですが、それに加えてと2に関して。例えば以下のようなエラーコードとエラーのメッセージを取得できるように定義したとします。
public enum ResultCode { // エラーコード,エラーメッセージのID OK(200, R.string.result_code_ok), ERROR_FORBIDDEN(403, R.string.result_error_fobidden), ERROR_NOTFOUND(404, R.string.result_error_notfound), ERROR_INTERNAL_SERVER(503, R.string.result_error_internalserver), ERROR_UNKNOWN(999, R.string.result_error_unknown),; int code,id; ResultCode(int code, int id) { this.code = code; this.id = id; } // idからエラーメッセージを取得して返す public String getMessage(Resources r) { return r.getString(id); } // エラーコードを返す public int getErrorCode() { return this.code; } }
これを任意のメソッドの戻り値として利用することができます。こんな感じで
public ResultCode function() { String page_content = null; // ..... if(null == page_content) { return ResultCode.ERROR_NOTFOUND; } return ResultCode.OK; }
呼び出し元の戻り値ではgetErrorCodeでエラーコードを取得でき、getMessageでエラーメッセージを取得できます。エラーメッセージは、getMessageメソッドでstrings.xml経由で定義したIDから文字列に変換する工夫がしてあります。こうしておけば、多言語対応にも便利です。
switch文の判定には、前述の通り直接シンボル名で判定できます。下記サンプルは先ほどのエラーをswitch文で判定してメッセージ(Toast)の表示方法を分岐しています。ERROR_FORBIDDENの場合のメッセージはこんな感じで画面に
private void dispErrorMessage(ResultCode result) { Resources resources = this.getResources(); switch(result) { // ResultCode型として判定できる↓ case OK: // なにもしない break; case ERROR_FORBIDDEN: case ERROR_NOTFOUND: case ERROR_INTERNAL_SERVER: // エラーを画面に表示 String error_message = result.getErrorCode() + ":" + result.getMessage(resources); Toast.makeText(this, error_message, Toast.LENGTH_SHORT).show(); break; default: Toast.makeText(this, ResultCode.ERROR_UNKNOWN.getMessage(resources), Toast.LENGTH_LONG).show(); break; } }
で、特徴の3つめですが、例えばEnumで定義したものをspinnerウィジェットへ表示させている場合、spinnerでは何番目が選択されかを返しますが、それがEnumで定義したどれに当たるか知りたい時があるかもしれません。その時に、Enumの定義をvalues()メソッドで配列として取得できるので、この配列の何番目かを見れば紐付けられます。
サンプルでは、spinnerウェジェットに表示されているいずれかのスイーツを選択すると、Toastに値段を表示するものです。
↓
Enumの定義
public enum Sweets { // スイーツ名, 値段 ECLAIR(R.string.spin_product_name_eclair, R.string.spin_product_price_eclair), FROZEN_YOGURT(R.string.spin_product_name_froyo, R.string.spin_product_price_froyo), GINGERBREAD(R.string.spin_product_name_gingerbread, R.string.spin_product_price_gingerbread), ICE_CREAM_SANDWICH(R.string.spin_product_name_ics, R.string.spin_product_price_ics); int id_name,id_price; Sweets(int id_name, int id_price) { this.id_name = id_name; this.id_price = id_price; } public String getName(Resources r) { return r.getString(this.id_name); } public String getPrice(Resources r) { return r.getString(this.id_price); } }
spinner側の処理
Resources resources = this.getResources(); final Sweets[] values = Sweets.values(); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // アイテムを追加します for(Sweets value : values) { adapter.add(value.getName(resources)); } Spinner spinner = (Spinner) findViewById(R.id.spinner1); // アダプターを設定します spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { Resources resources = MainActivity.this.getResources(); String message = "値段:" + values[position].getPrice(resources); Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show(); } @Override public void onNothingSelected(AdapterView<?> arg0) {} });
onItemSelectedはspinnerの項目が選択されたタイミングで実行されます。Sweetsのvalues()で取得される配列とそのメソッドで渡されるpositionで紐付けてものをgetPriceをする事で値段の文字列を取得しています。
上記の全ソースはGithubへアップしました。
・takaiwa/EnumSample · GitHub
追記:2012/11/08
onItemSelected内のようなpositionが得られる場面でswitch文を使う場合
switch(values[position]) { case ECLAIR: break; case FROZEN_YOGURT: break; case GINGERBREAD: break; case ICE_CREAM_SANDWICH: break; }
追記:2013/06/13
入れ子を表現
文字列で定義
public enum Baz{ yin("yang"), yang("yin"), good("evil"), evil("good"); private String opposite; Baz(String opposite){ this.opposite = opposite; } public Baz getOpposite(){ return Baz.valueOf(opposite); } }
switch文で定義
public enum Baz{ yin, yang, good, evil; public Baz getOpposite() { switch (this) { case yin: return yang; case yang: return yin; case good: return evil; case evil: return good; } throw new AssertionError(); }
参考:Java enum- Cannot reference a field before it is defined - Stack Overflow
PR:オラクル認定資格教科書 Javaプログラマ Bronze SE 7 スピードマスター問題集 (EXAMPRESS)
PR:Java言語プログラミングレッスン 第3版(上)
コメント
コメントを投稿