回答編集履歴
8
Pokemonのコンストラクタを private 化
test
CHANGED
@@ -62,7 +62,7 @@
|
|
62
62
|
final String name;
|
63
63
|
private Action[] actions = new Action[3];
|
64
64
|
|
65
|
-
Pokemon(String name) {
|
65
|
+
private Pokemon(String name) {
|
66
66
|
this.name = name;
|
67
67
|
}
|
68
68
|
@Override
|
7
サンプルコード
test
CHANGED
@@ -8,6 +8,130 @@
|
|
8
8
|
|
9
9
|
---
|
10
10
|
|
11
|
+
>「Species」に151種の列挙定数を、「Move」に165種の列挙定数を、「Type」に15種
|
12
|
+
|
13
|
+
ということですが、上で書いたのと同じく私なら Species と Move は enum にはしません。 Type は enum が妥当と考えます。
|
14
|
+
ポケモンを P(p)okemon, 技を A(a)ction としてやってみると以下な感じ。
|
15
|
+
|
16
|
+
pokemon.csv
|
17
|
+
```csv
|
18
|
+
ポケモン1, たいあたり, みずでっぽう, null
|
19
|
+
ポケモン2, たいあたり, ひのこ, なきごえ
|
20
|
+
```
|
21
|
+
action.csv
|
22
|
+
```csv
|
23
|
+
たいあたり, NORMAL, PHYSICAL, 50, 30, THREE
|
24
|
+
みずでっぽう, WATER, SPECIAL, 10, 10, THREE
|
25
|
+
ひのこ, FIRE, SPECIAL, 20, 20, THREE
|
26
|
+
つるのむち, GRASS, SPECIAL, 30, 30, THREE
|
27
|
+
なきごえ, NORMAL, STATUS, 40, 40, THREE
|
28
|
+
```
|
29
|
+
Pokemon.java
|
30
|
+
```java
|
31
|
+
import java.io.*;
|
32
|
+
import java.util.HashMap;
|
33
|
+
import java.util.Map;
|
34
|
+
|
35
|
+
public class Pokemon {
|
36
|
+
public static void main(String[] args) throws IOException {
|
37
|
+
Map<String,Action> actionMap = Action.readCsv("action.csv");
|
38
|
+
Map<String,Pokemon> map = Pokemon.readCsv("pokemon.csv", actionMap);
|
39
|
+
for(Pokemon p : map.values()) System.out.println("pokemon="+p);
|
40
|
+
}
|
41
|
+
|
42
|
+
private static Map<String,Pokemon> readCsv(String filename, Map<String,Action> actionMap) throws IOException {
|
43
|
+
Map<String,Pokemon> map = new HashMap<>();
|
44
|
+
try(BufferedReader r = new BufferedReader(new FileReader(filename))) {
|
45
|
+
for(String line; (line=r.readLine()) != null; ) {
|
46
|
+
String[] tokens = line.split(", *");
|
47
|
+
if(tokens.length != 4) throw new IOException("format error: line="+line);
|
48
|
+
if(map.containsKey(tokens[0])) throw new IOException("overloaded: line="+line);
|
49
|
+
Pokemon p = new Pokemon(tokens[0]);
|
50
|
+
map.put(tokens[0], p);
|
51
|
+
for(int i=0; i<3; i++) {
|
52
|
+
if(tokens[1+i].equals("null")) continue;
|
53
|
+
Action action = actionMap.get(tokens[1+i]);
|
54
|
+
if(action == null) throw new IOException("action not found: line="+line);
|
55
|
+
p.actions[i] = action;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
return map;
|
60
|
+
}
|
61
|
+
|
62
|
+
final String name;
|
63
|
+
private Action[] actions = new Action[3];
|
64
|
+
|
65
|
+
Pokemon(String name) {
|
66
|
+
this.name = name;
|
67
|
+
}
|
68
|
+
@Override
|
69
|
+
public String toString(){
|
70
|
+
return super.toString()+"["+name+","+actions[0]+","+actions[1]+","+actions[2]+"]";
|
71
|
+
}
|
72
|
+
}
|
73
|
+
|
74
|
+
enum Type {
|
75
|
+
NORMAL, WATER, FIRE, GRASS
|
76
|
+
}
|
77
|
+
enum Category {
|
78
|
+
PHYSICAL, SPECIAL, STATUS
|
79
|
+
}
|
80
|
+
enum Priority {
|
81
|
+
ONE, TWO, THREE
|
82
|
+
}
|
83
|
+
|
84
|
+
class Action {
|
85
|
+
static Map<String,Action> readCsv(String filename) throws IOException {
|
86
|
+
Map<String,Action> map = new HashMap<>();
|
87
|
+
try(BufferedReader r = new BufferedReader(new FileReader(filename))) {
|
88
|
+
for(String line; (line=r.readLine()) != null; ) {
|
89
|
+
String[] tokens = line.split(", *");
|
90
|
+
if(tokens.length != 6) throw new IOException("format error: line="+line);
|
91
|
+
if(map.containsKey(tokens[0])) throw new IOException("overloaded: line="+line);
|
92
|
+
try {
|
93
|
+
map.put(tokens[0], new Action(tokens[0],
|
94
|
+
Type.valueOf(tokens[1]),
|
95
|
+
Category.valueOf(tokens[2]),
|
96
|
+
Integer.parseInt(tokens[3]),
|
97
|
+
Integer.parseInt(tokens[4]),
|
98
|
+
Priority.valueOf(tokens[5])));
|
99
|
+
} catch(IllegalArgumentException e) {
|
100
|
+
throw new IOException("format error: line="+line, e);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
}
|
104
|
+
return map;
|
105
|
+
}
|
106
|
+
|
107
|
+
final String name; // 名
|
108
|
+
final Type type; // タイプ
|
109
|
+
final Category category; // 型(ぶつり/とくしゅ/へんか)
|
110
|
+
final int power; // 威力
|
111
|
+
final int pp; // 使用最大回数
|
112
|
+
final Priority priority; // 優先度
|
113
|
+
|
114
|
+
private Action(String name, Type type, Category category, int power, int pp, Priority priority) {
|
115
|
+
this.name = name;
|
116
|
+
this.type = type;
|
117
|
+
this.category = category;
|
118
|
+
this.power = power;
|
119
|
+
this.pp = pp;
|
120
|
+
this.priority = priority;
|
121
|
+
}
|
122
|
+
|
123
|
+
@Override
|
124
|
+
public String toString(){
|
125
|
+
return super.toString()+"["+name+","+type+","+category+","+power+","+pp+","+priority+"]";
|
126
|
+
}
|
127
|
+
}
|
128
|
+
```
|
129
|
+
実行
|
130
|
+
```
|
131
|
+
pokemon=Pokemon@85ede7b[ポケモン1,Action@5674cd4d[たいあたり,NORMAL,PHYSICAL,50,30,THREE],Action@63961c42[みずでっぽう,WATER,SPECIAL,10,10,THREE],null]
|
132
|
+
pokemon=Pokemon@65b54208[ポケモン2,Action@5674cd4d[たいあたり,NORMAL,PHYSICAL,50,30,THREE],Action@1be6f5c3[ひのこ,FIRE,SPECIAL,20,20,THREE],Action@6b884d57[なきごえ,NORMAL,STATUS,40,40,THREE]]
|
133
|
+
```
|
134
|
+
|
11
135
|
enum は端的にはメソッド呼び出しで範囲のあるパラメータの指定間違いをコンパイルエラーで取り易くするというだけです。
|
12
136
|
プログラムが扱う(ファイル等から取得する)データの値の範囲をコンパイルエラーとして取り除くことは出来ません。
|
13
137
|
結局プログラムを動作させなければ分からないことですので、上に書いたようにファイルの読み込み時にそれぞれの値をチェックするというのは enum でも普通の class でも同じですし、普通のオブジェクトに保存した値を変更できなくすれば読み込んだ後に不正値になる心配もありません。
|
6
追加
test
CHANGED
@@ -5,3 +5,9 @@
|
|
5
5
|
なお、 enum (の定義自体)が沢山あるのと enum のメンバ(オブジェクト)が沢山あるのは違いますので、表現はご注意された方が良いと思います。
|
6
6
|
|
7
7
|
csv 等から enum を import する場合は getById メソッドのようなもので enum に戻すことになるので、そこで不正値なら例外を発すれば、基本的な型の安全は保てます。(null を返すのは発見が遅れるので好ましくないと考えます。)
|
8
|
+
|
9
|
+
---
|
10
|
+
|
11
|
+
enum は端的にはメソッド呼び出しで範囲のあるパラメータの指定間違いをコンパイルエラーで取り易くするというだけです。
|
12
|
+
プログラムが扱う(ファイル等から取得する)データの値の範囲をコンパイルエラーとして取り除くことは出来ません。
|
13
|
+
結局プログラムを動作させなければ分からないことですので、上に書いたようにファイルの読み込み時にそれぞれの値をチェックするというのは enum でも普通の class でも同じですし、普通のオブジェクトに保存した値を変更できなくすれば読み込んだ後に不正値になる心配もありません。
|
5
追加修正
test
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
何個でも、必要なら作れば良いのでは無いでしょうか。
|
2
|
-
問題があるかどうかは環境に依る部分が大きいと思いますので、やってみれば分かることで
|
3
|
-
私なら、型やタイプ(ポケモンやらないので違いが分かりません)はともかく、 Move 自体は enum にはしないで csv から読んでの普通のクラス/オブジェクトにするでしょう。
|
2
|
+
問題があるかどうかは環境に依る部分が大きいと思いますので、やってみれば分かることです。
|
3
|
+
でも私なら、型やタイプ(ポケモンやらないので違いが分かりません)はともかく、 Move 自体は enum にはしないで csv から読んでの普通のクラス/オブジェクトにするでしょう。技が何百種類あろうがある瞬間に同時に必要なのは幾つかだけなら、その都度オブジェクトを生成・削除すれば資源は最小限で済むはずです。そして今すぐそこまでの機能が必要な訳では無さそうですので、技オブジェクトの取得部分を取り替えられるようにしておいて、今は適当に返すようにします。
|
4
4
|
|
5
5
|
なお、 enum (の定義自体)が沢山あるのと enum のメンバ(オブジェクト)が沢山あるのは違いますので、表現はご注意された方が良いと思います。
|
6
6
|
|
7
|
-
csv 等から enum を i
|
7
|
+
csv 等から enum を import する場合は getById メソッドのようなもので enum に戻すことになるので、そこで不正値なら例外を発すれば、基本的な型の安全は保てます。(null を返すのは発見が遅れるので好ましくないと考えます。)
|
4
修正
test
CHANGED
@@ -4,4 +4,4 @@
|
|
4
4
|
|
5
5
|
なお、 enum (の定義自体)が沢山あるのと enum のメンバ(オブジェクト)が沢山あるのは違いますので、表現はご注意された方が良いと思います。
|
6
6
|
|
7
|
-
csv 等
|
7
|
+
csv 等から enum を inport する場合は getById メソッドのようなもので enum に戻すことになるので、そこで不正値なら例外を発すれば、基本的な型の安全は保てるでしょう。(null を返すのは発見が遅れるので好ましくないと考えます。)
|
3
修正
test
CHANGED
@@ -3,3 +3,5 @@
|
|
3
3
|
私なら、型やタイプ(ポケモンやらないので違いが分かりません)はともかく、 Move 自体は enum にはしないで csv から読んでの普通のクラス/オブジェクトにするでしょう。
|
4
4
|
|
5
5
|
なお、 enum (の定義自体)が沢山あるのと enum のメンバ(オブジェクト)が沢山あるのは違いますので、表現はご注意された方が良いと思います。
|
6
|
+
|
7
|
+
csv 等に export した enum は当然 getById メソッドのようなもので enum に戻すことになるので、そこで不正値なら例外を発すれば、基本的な型の安全は保てるでしょう。(null を返すのは発見が遅れるので好ましくないと考えます。)
|
2
修正
test
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
何個でも、必要なら作れば良いのでは無いでしょうか。
|
2
2
|
問題があるかどうかは環境に依る部分が大きいと思いますので、やってみれば分かることでしょう。
|
3
|
-
な
|
3
|
+
私なら、型やタイプ(ポケモンやらないので違いが分かりません)はともかく、 Move 自体は enum にはしないで csv から読んでの普通のクラス/オブジェクトにするでしょう。
|
4
4
|
|
5
|
-
|
5
|
+
なお、 enum (の定義自体)が沢山あるのと enum のメンバ(オブジェクト)が沢山あるのは違いますので、表現はご注意された方が良いと思います。
|
1
修正
test
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
何個でも、必要なら作れば良いのでは無いでしょうか。
|
2
2
|
問題があるかどうかは環境に依る部分が大きいと思いますので、やってみれば分かることでしょう。
|
3
|
+
なお、 enum (の定義)が沢山あるのと enum のメンバ(オブジェクト)が沢山あるのは違いますので、表現はご注意された方が良いと思います。
|
3
4
|
|
4
5
|
ちなみに、 enum の保持するデータは変更しないでしょうから、フィールドを private にして getter で読むのでは無く、 フィールドを public(もしくはパッケージプライベート) final にしてしまえば getter は必要ありません。
|