아이템38 - 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라
열거형의 단점
- 우리가 쓰는 Enum의 특징으로는 클라이언트가 값을 더 추가해서 쓸 수 없다
- 예시로 Spring
HttpMethod httpMethod
은 우리가 값을 추가할수 없는데 잘 생각해보면 그럴필요가 없다
- 생각해보면 확장할 필요가 있는경우가 드물다.. HttpMethod 같은걸 일개 개발자가 추가할리는 없으니..까?
@Slf4j
@RestController
public class RequestHeaderController {
@RequestMapping("/header")
public String headers(HttpServletRequest request, HttpServletResponse response,
HttpMethod httpMethod, Locale locale,
@RequestHeader MultiValueMap<String, String> headerMap,
@RequestHeader("host") String host,
@CookieValue(value = "myCookie", required = false) String cookie) {
public enum HttpMethod {
GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
static {
for (HttpMethod httpMethod : values()) {
mappings.put(httpMethod.name(), httpMethod);
}
}
@Nullable
public static HttpMethod resolve(@Nullable String method) {
return (method != null ? mappings.get(method) : null);
}
public boolean matches(String method) {
return name().equals(method);
}
}
그럼에도 불구하고
- 과거에 사용했던 타입안전 열거패턴은 가능했는데 이런게 필요한 경우가 있을까??
- 딱하나 있다면 연산자(Op code)같은게 있을수 있고, 이때는 Enum 으로 인터페이스를 구현하는 방식을 사용하면된다
public interface Operation {
double apply(double x, double y);
}
public enum BasicOps implements Operation {
PULS("+") {
@Override
public double apply(double x, double y) {
return x + y;
}
},
MINUS("+") {
},
TIMES("*") {
},
DIVIDE("/") {
};
private final String symbol;
BasicOps(String symbol) {
this.symbol = symbol;
}
}
위와 같은 코드를 프레임워크가 만들어줬다고 하면, 클라이언트가 아래 코드를 추가할 수 있다
public enum ExtenedOps implements Operation {
EXP("*") {
@Override
public double apply(double x, double y) {
return x * y;
}
},
REMAINDER("%") {
}
}