정수 열거 패턴
•
자바에서 열거 타입을 지원하기 전에는 아래와 같이 정수 상수들을 선언해 사용했었다.
public final static int MONDAY = 1;
public final static int TUESDAY = 2;
public final static int WEDNESDAY = 3;
public final static int THURSDAY = 4;
public final static int FRIDAY = 5;
public final static int SATURDAY = 6;
public final static int SUNDAY = 7;
Java
복사
•
이와 같은 방식은 타입 안전을 보장할 방법이 없고 가독성과 표현력 전부 좋지 않다.
•
또한 정수 상수를 문자열로 출력하기가 다소 까다롭다. 값을 출력하거나 디버깅을 할 때에도 단순한 숫자로 보이기 때문에 별로 도움이 되지 않는다.
•
이에 정수 대신 문자열 상수를 나열하여 사용하는 변형 패턴도 있었는데, 이 변형은 이름 대신 문자열 그대로 하드코딩하게 만들고 오타가 있어도 컴파일러에서 알 수 없으니 런타임 에러가 자주 발생한다.
열거 타입
enum Season {
SPRING, SUMMER, FALL, WINTER;
}
enum Operation {
PLUS, MINUS, TIMES, DIVDE;
}
Java
복사
•
C, C++, C# 같은 다른 언어의 열거 타입과 비슷해보이지만, 자바의 열거 타입은 완전한 형태의 클래스로 다른 언어의 열거 타입보다 강력하다.
•
열거 타입 자체는 클래스이며, 열거 타입 내 상수 하나당 자신의 인스턴스를 하나씩 만들어 public static final 필드로 공개한다. 추가적으로 외부에서 접근할 수 있는 생성자를 제공하지 않아 final과 다를 바 없고, 그렇기에 열거 타입 선언으로 만들어진 인스턴스가 딱 하나씩만 존재한다는 것을 보장할 수 있다.
•
열거 타입 변수나 매개변수로 받았다면 해당 열거 타입의 상수 중 하나임이 보장되기 때문에, 열거 타입은 컴파일타임 타입 안전성을 제공한다.
열거 타입 매핑
enum Season {
SPRING("봄"),
SUMMER("여름"),
FALL("가을"),
WINTER("겨울");
// 문자열을 저장할 필드
private String season;
// private 생성자 (싱글톤)
private Season(String season) {
this.season = season;
}
public String getSeason() {
return season;
}
}
Java
복사
•
열거 타입 생성자에서 데이터를 받아 인스턴스 필드에 저장하여, 각각의 상수 인스턴스를 생성할 때 값을 저장하도록 만들면 된다.
public static void main(String[] args) throws Exception {
Season s = Season.SUMMER;
System.out.println(s.name()); // 열거 객체명 출력 : SUMMER
System.out.println(s.getSeason()); // 매핑된 열거 데이터 출력 : 봄
}
Java
복사
•
이와 같이 데이터와 메서드를 같은 열거 타입으로 각 열거 타입에서 값을 가지고 있게 만들고, 해당 값을 언제든 꺼내어 사용할 수 있다.
열거 타입 확장
•
각 상수마다 별도의 연산을 수행할 수 있게 만들고 싶다면 아래와 같이 코드를 작성하게 될 것이다.
public enum Operation {
PLUS, MINUS, TIMES, DIVDE;
// 상수마다의 연산을 수행한다.
public double apply(double x, double y) {
switch(this) {
case PLUS: return x + y;
case MINUS: return x - y;
case TIMES: return x * y;
case DIVIDE: return x / y;
}
throw new AssertionError("알 수 없는 연산: " + this);
}
}
Java
복사
•
이 코드는 동작은 하지만, 상수값이 추가될 경우 case문을 추가로 작성해야하고 별로 보기에 좋지 않다.
•
이에 대한 더 나은 구현 방법은, 열거 타입에 추상 메서드를 선언하고 각 상수별 클래스 몸체(constant-specific class body)에서 자신에 맞게 재정의하는 것이다.
public enum 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}};
public abstract double apply(double x, double y);
}
Java
복사