π 1. μ΄κ±° νμ μ νμ₯
νμ μμ μ΄κ±° ν¨ν΄κ³Ό λ¬λ¦¬ μ΄κ±° νμ μ νμ₯ν μ μλ€. (μ΄ μ μ μ μΈνκ³ λ κ±°μ λͺ¨λ μν©μμ μ΄κ±° νμ μ΄ νμ μμ μ΄κ±° ν¨ν΄(typesafe enum pattern) λ³΄λ€ μ°μνλ€.)
νμ μμ μ΄κ±° ν¨ν΄μ μ΄κ±°ν κ°λ€μ κ·Έλλ‘ κ°μ Έμ¨ λ€μ κ°μ λ μΆκ°νμ¬ λ€λ₯Έ λͺ©μ μΌλ‘ μΈ μ μλ λ°λ©΄, μ΄κ±° νμ μ κ·Έλ κ² ν μ μλ€.
μ€κ³κ° μ λͺ» λ κ²μ μλλ€. νμ§λ§ λ€μκ³Ό κ°μ μ΄μ λ‘ λλΆλΆ μν©μμ μ΄κ±° νμ μ νμ₯νλ 건 μ’μ§ μμ μκ°μ΄κΈ° λλ¬Έμ΄λ€ μ΄κ±° νμ μ νμ₯ν μ μλλ‘ μ€κ³ν κ²μ΄λ€.
- νμ₯ν νμ μ μμλ κΈ°λ° νμ μ μμλ‘ μ·¨κΈνμ§λ§, κΈ°λ° νμ μ μμλ₯Ό νμ₯ν νμ μ μμλ‘ μ·¨κΈν μ μλ 건 μ΄μνκΈ° λλ¬Έμ΄λ€.
- κΈ°λ° νμ κ³Ό νμ₯λ νμ λ€μ μμ λͺ¨λλ₯Ό μνν λ°©λ²μ΄ λ§λ μΉ μλ€.
- νμ₯μ±μ λμ΄λ €λ©΄ κ³ λ €ν μμκ° λμ΄λ μ€κ³μ ꡬνμ΄ λ 볡μ‘ν΄μ§λ€.
κ·Έλ¬λ μ°μ° μ½λ(operation code νΉμ opcode)λ νμ₯ν μ μλ μ΄κ±° νμ μ΄ μ΄μΈλ¦¬λ μ°μμ΄λ€.
APIκ° μ 곡νλ κΈ°λ³Έ μ°μ° μΈμ μ¬μ©μ νμ₯ μ°μ°μ μΆκ°ν μ μλλ‘ μ΄μ΄μ€μΌ ν λκ° μλλ°, μ΄κ±° νμ μΌλ‘ μ΄ ν¨κ³Όλ₯Ό λνλΌ μ μλ λ°©λ²μ΄ μλ€. μ§κΈλΆν° κ·Έ λ°©λ²μ λν΄ μμ보μ.
π 2. μΈν°νμ΄μ€λ₯Ό νμ©ν νμ₯ κ°λ₯ν μ΄κ±° νμ
μ΄κ±° νμ μ μμμ μΈν°νμ΄μ€λ₯Ό ꡬνν μ μλ€. κ·Έλμ μ°μ° μ½λλ₯Ό νμ₯νκ³ μΆλ€λ©΄, μ°μ° μ½λμ© μΈν°νμ΄μ€λ₯Ό μ μνκ³ μ΄κ±° νμ μ΄ μ΄ μΈν°νμ΄μ€λ₯Ό ꡬννκ² νλ©΄ λλ€.
public interface Operation {
double apply(double x, double y);
}
public enum BasicOperation implements Operation {
PLUS("+") {
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
public double apply(double x, double y) {
return x - y;
}
},
TIMES("*") {
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
public double apply(double x, double y) {
return x / y;
}
};
private final String symbol;
BasicOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
μ΄λ κ² νλ©΄ Operationμ ꡬνν λ λ€λ₯Έ μ΄κ±° νμ μΈ ExtendedOperationμ μ μν΄ κΈ°λ³Έ νμ μΈ BasicOperationμ λ체ν μ μλ€.
public enum ExtendedOperation implements Operation {
EXP("^") {
public double apply(double x, double y) {
return Math.pow(x, y);
}
},
REMAINDER("%") {
public double apply(double x, double y) {
return x % y;
}
};
private final String symbol;
ExtendedOperation(String symbol) {
this.symbol = symbol;
}
@Override public String toString() {
return symbol;
}
}
μλ‘ μμ±ν μ°μ°μ κΈ°μ‘΄ μ°μ°μ μ°λ κ³³μ΄λ©΄ μ΄λλ μΈ μ μλ€.
κ°λ³ μΈμ€ν΄μ€ μμ€μμλΏλ§ μλλΌ νμ μμ€μμλ, κΈ°λ³Έ μ΄κ±° νμ λμ νμ₯λ μ΄κ±° νμ μ λ겨 νμ₯λ μ΄κ±° νμ μ μμ λͺ¨λλ₯Ό μ¬μ©νκ² ν μλ μλ€.
public static void main(String[] args) {
double x = 3d;
double y = 2d;
test(ExtendedOperation.class, x, y);
}
private static <T extends Enum<T> & Operation> void test(Class<T> opEnumType, double x, double y) {
for(Operation op : opEnumType.getEnumConstants()) {
System.out.printf("%f %s %f = %f%n",
x, op, y, op.apply(x, y));
}
// μΆλ ₯ κ²°κ³Ό
// 3.000000 ^ 2.000000 = 9.000000
// 3.000000 % 2.000000 = 1.000000
}
opEnumType 맀κ°λ³μμ μ μΈ(<T extends Enum<T> & Operation> Class<T>)λ Class κ°μ²΄κ° μ΄κ±° νμ μΈ λμμ Operationμ νμ νμ μ΄μ΄μΌ νλ€λ λ»μ΄λ€.
Class κ°μ²΄ λμ νμ μ μμΌλμΉ΄λ νμ μ μ΄μ©ν μλ μλ€.
public static void main(String[] args) {
double x = 3d;
double y = 2d;
test(Arrays.asList(ExtendedOperation.values()), x, y);
}
private static void test(Collection<? extends Operation> opSet,
double x,
double y) {
for(Operation op : opSet) {
System.out.printf("%f %s %f = %f%n",
x, op, y, op.apply(x, y));
}
// μΆλ ₯ κ²°κ³Ό
// 3.000000 ^ 2.000000 = 9.000000
// 3.000000 % 2.000000 = 1.000000
}
π 3. λ¬Έμ μ
μΈν°νμ΄μ€λ₯Ό μ΄μ©ν΄ νμ₯ κ°λ₯ν μ΄κ±° νμ μ νλ΄ λ΄λ λ°©μμλ ν κ°μ§ μ¬μν λ¬Έμ κ° μλ€. λ°λ‘ μ΄κ±° νμ λΌλ¦¬ ꡬνμ μμν μ μλ€λ κ²μ΄λ€.
μ무 μνμλ μμ‘΄νμ§ μλλ€λ©΄ λν΄νΈ ꡬνμ μ΄μ©ν΄ μΈν°νμ΄μ€μ μΆκ°ν μ μλ€.
νμ§λ§, μμ μμμμ μ΄ν΄λ³Έ κ²μ²λΌ μ°μ° κΈ°νΈλ₯Ό μ μ₯νκ³ μ°Ύλ λ‘μ§μ΄ BasicOperationκ³Ό ExtendedOperation λͺ¨λμ λ€μ΄μλ κ²μ νμΈν μ μλ€.
곡μ νλ κΈ°λ₯μ΄ λ§λ€λ©΄ κ·Έ λΆλΆμ λ³λμ λμ°λ―Έ ν΄λμ€λ μ μ λμ°λ―Έ λ©μλλ‘ λΆλ¦¬νλ λ°©μμΌλ‘ μ½λ μ€λ³΅μ μμ¨ μ μμ κ²μ΄λ€.
ν΄λΉ κΈμ Joshua Block λμ 'Effective Java 3/E'λ₯Ό μ°Έκ³ νμμ΅λλ€.