##Javaのenum
Javaのenumはとっても高機能で次のように複数のフィールドやメソッドを持つenumを作ることができる。
Java.Color.java
enum Color {
RED("赤", 255, 0, 0),
YELLOW("黄色", 255, 255, 0),
GRAY("灰色", 155, 155, 155);
Color(String name, int r, int g, int b) {
this.name = name;
this.r = r;
this.g = g;
this.b = b;
}
public String name;
public int r, g, b;
public String toHexCode() {
return String.format("#%02x%02x%02x", r, g, b);
}
}
System.out.println(Color.YELLOW.toHexCode()); // => "#ffff00"
System.out.println(Color.GRAY.name); // => "灰色"
##JavaScriptで実装
これをJavaScriptで素直に実装するときっとこんな感じになるかと思う。
JavaScript.color.js
var Color = (function() {
var InnerType = function(name, r, g, b) {
this.name = name;
this.r = r;
this.g = g;
this.b = b;
};
InnerType.prototype.toHexCode = function() {
return '#' + ('00' + this.r.toString(16)).slice(-2) + ('00' + this.g.toString(16)).slice(-2) + ('00' + this.b.toString(16)).slice(-2);
};
return {
RED : new InnerType('赤', 255, 0, 0),
YELLOW : new InnerType('黄色', 255, 255, 0),
GRAY : new InnerType('灰色', 155, 155, 155)
};
})();
console.log(Color.YELLOW.toHexCode()); // => "#ffff00"
console.log(Color.GRAY.name); // => "灰色"
一見良さそうだけど、、、
JavaではこのenumをMapのkeyに使ったりが当たり前にできるが
Map<Color, Integer> colorNums = new HashMap<>();
colorNums.put(Color.RED, 10);
colorNums.put(Color.YELLOW, 20);
colorNums.put(Color.GRAY, 30);
System.out.println(colorNums.get(Color.RED)); // => "10"
System.out.println(colorNums.get(Color.YELLOW)); // => "20"
JavaScript版だと、
var colorNum = {};
colorNum[Color.RED] = 10;
colorNum[Color.YELLOW] = 20;
colorNum[Color.GRAY] = 30;
console.log(colorNum[Color.RED]); // => "30" !!?
console.log(colorNum[Color.YELLOW]); // => "30" !!?
と、意図通りの挙動にならなかったり。
Color.RED, Color.YELLOW, Color.GRAYはオブジェクトなので、連想配列のキーになったときにオブジェクトのデフォルトのtoStringが呼び出されてしまい、3つとも"[object Object]"になってしまうのが原因。
##JavaScriptで実装(修正版)
なので、次のようにtoStringでそれぞれに固有の文字列を返すようにすると意図通りに動く。
JavaScript.color_fix.js
var Color = (function() {
const InnerType = function(name, r, g, b, toStringValue) {
this.name = name;
this.r = r;
this.g = g;
this.b = b;
this.toString = function() {
return toStringValue;
};
};
InnerType.prototype.toHexCode = function() {
return '#' + ('00' + this.r.toString(16)).slice(-2) + ('00' + this.g.toString(16)).slice(-2) + ('00' + this.b.toString(16)).slice(-2);
};
return {
RED : new InnerType('赤', 255, 0, 0, 'RED'),
YELLOW : new InnerType('黄色', 255, 255, 0, 'YELLOW'),
GRAY : new InnerType('灰色', 155, 155, 155, 'GRAY')
};
})();
var colorNum = {};
colorNum[Color.RED] = 10;
colorNum[Color.YELLOW] = 20;
colorNum[Color.GRAY] = 30;
console.log(colorNum[Color.RED]); // => "10"
console.log(colorNum[Color.YELLOW]); // => "20"
めでたしめでたし。
##JavaScriptで実装(ES6版)
ただ、toString用の文字列を自分で指定するのが少し残念なので、ES6が使えるのならSymbol()を使って自動化すると良い感じ。
JavaScript.color_fix_es6.js
const Color = (() => {
const InnerType = function(name, r, g, b) {
this.name = name;
this.r = r;
this.g = g;
this.b = b;
const sym = Symbol();
this.toString = () => sym;
};
InnerType.prototype.toHexCode = function() {
return '#' + ('00' + this.r.toString(16)).slice(-2) + ('00' + this.g.toString(16)).slice(-2) + ('00' + this.b.toString(16)).slice(-2);
};
return {
RED : new InnerType('赤', 255, 0, 0),
YELLOW : new InnerType('黄色', 255, 255, 0),
GRAY : new InnerType('灰色', 155, 155, 155)
};
})();
Javaのenum最強だけど、ほぼ同じことを実現できるJavaScriptの柔軟性よしよし。