싱글턴 패턴을 공부하다가 이넘을 만났다.
귀여니체가 아니라 열거 타입 enum 말이다.
마주친 김에 간단히 알아보려고 한다.
우선, 열거 타입이라는 말이 좀 생소할 것이다.
데이터를 왜 열거해야 하지...? 라는 생각이 들 수도 있겠지만,
그 의미는 조금 이따가 알아보고 기본적인 사용법부터 익혀보자.
1. 기본적인 사용법
<상황>
환승연애2 출연진의 이름을 저장하고 싶다.
가장 먼저 떠오르는 방법은 클래스에 상수로 저장하는 방법이다.
출연진 리스트를 상수로 초기화하면 List#set() 메소드 등에 의해 요소가 변경될 수 있으므로
출연진들을 한 명씩 상수로 저장해야 한다.
아마 이런 형태가 될 것이다.
public class Cast { // 출연자
public static final String 이나연 = "이나연";
public static final String 남희두 = "남희두";
public static final String 성해은 = "성해은";
public static final String 정규민 = "정규민";
public static final String 이지연 = "이지연";
public static final String 김태이 = "김태이";
public static final String 김지수 = "김지수";
public static final String 박원빈 = "박원빈";
public static final String 최이현 = "최이현";
public static final String 선민기 = "선민기";
}
데이터는 간단한데, 막상 구현하는 형태가 굉장히 복잡하다.
왜냐면 클래스는 상수를 저장하기 위해 만들어지지 않았기 때문이다.
이럴 때 사용하는 것이 바로 enum이다.
enum을 사용하면 이렇게 구현할 수 있다.
public enum Cast {
이나연,
남희두,
성해은,
정규민,
이지연,
김태이,
김지수,
박원빈,
최이현,
선민기
}
보기만 해도 깔끔하다.
정확한 설명은 조금 아래에서 하겠다.
<상황2>
환승연애2 출연진의 이름과 전 연인(x), 성격 유형(mbti)을 저장하고 싶다.
이 상황을 클래스로 구현하기 위해선 전 연인과 최종 선택을 멤버로 가지는 출연자 클래스를 만들고,
출연자 상수를 한 클래스에 모아두어야 한다.
근데 두 클래스가 같으면 안될까?
말하자면, Cast 클래스 내부에 Cast 타입 상수를 모아두는 것이다.
안될 것은 없다.
이런 식으로 구현할 수 있다.
public class Cast {
public static final Cast 이나연 = new Cast("남희두", "남희두");
public static final Cast 남희두 = new Cast("이나연", "이나연");
public static final Cast 성해은 = new Cast("정규민", "정현규");
public static final Cast 정규민 = new Cast("성해은", null);
public static final Cast 이지연 = new Cast("김태이", null);
public static final Cast 김태이 = new Cast("이지연", "박나언");
public static final Cast 김지수 = new Cast("박원빈", null);
public static final Cast 박원빈 = new Cast("김지수", null);
public static final Cast 최이현 = new Cast("선민기", null);
public static final Cast 선민기 = new Cast("최이현", null);
public static final Cast 박나언 = new Cast("정현규", "김태이");
public static final Cast 정현규 = new Cast("박나언", "성해은");
private final String x;
private final String fin;
private Cast(String x, String fin) {
this.x = x;
this.fin = fin;
}
}
클래스로 구현하니 역시나 너무 복잡해보인다. 😵
하지만 enum으로는 이렇게 간단하게 구현할 수 있다!
public enum Cast {
이나연("남희두", "남희두"),
남희두("이나연", "이나연"),
성해은("정규민", "정현규"),
정규민("성해은", null),
이지연("김태이", null),
김태이("이지연", "박나언"),
김지수("박원빈", null),
박원빈("김지수", null),
최이현("선민기", null),
선민기("최이현", null),
박나언("정현규", "김태이"),
정현규("박나언", "성해은");
private final String x;
private final String fin;
Cast(String x, String fin) {
this.x = x;
this.fin = fin;
}
}
이 코드를 통해 enum 타입을 알아보자.
우선 아래의 두 코드는 같은 의미이다
[클래스 버전]
public static final Cast 이나연 = new Cast("남희두", "남희두");
[enum 버전]
이나연("남희두", "남희두")
보다시피 enum 내부의 객체는 자동으로 해당 enum 타입의 상수로 생성된다.(public static final Cast 생략)
그리고 상수 이름 옆에 생성자 메서드의 괄호 부분만 붙여주면 자동으로 객체를 생성해서 할당한다. (= new Cast 생략)
열거 타입 안에 있는 상수를 열거 상수라고 부르는데,
열거 상수는 상수기 때문에 당연히 필드와 생성자를 구현해야 한다.
위에서 봤듯이 enum은 상수를 저장하는 데에 최적화되어 있다.
2. 내장 함수
클래스 대신 enum을 썼을 때의 또 다른 좋은 점은 유용한 내장 함수를 활용할 수 있다는 점이다!
상황을 통해 내장 함수를 알아보자.
<상황3>
프로그램을 보다 보니 출연진들의 전 연인이 기억이 안 난다.
출연진의 이름을 투입하면 전 연인 객체를 반환하는 메소드를 만들어보자.
기본적으로 Cast 열거 타입의 x 멤버는 private으로 선언되었기 때문에 바깥에서 참조할 수 없다.
그러므로 Cast 열거 타입 내부의 상수를 일일이 순회하면서
그 열거 상수의 x 멤버가 입력된 멤버와 같은지 확인해야 한다.
실제로 코드를 보면서 확인하자.
public enum Cast {
...
public static Cast findXOf(Cast mem) {
return Arrays.stream(Cast.values())
.filter(c -> c.x.equals(mem.name()))
.findAny()
.orElse(null);
}
}
findXOf() 메서드의 리턴값을 한 줄 한 줄 따라가 보자.
우선, 첫째 줄의 static 메서드 values()는 열거 타입 내의 열거 상수를 순회한다.
둘째 줄의 name() 메서드는 열거 상수의 이름("이나연", "남희두" 등)을 반환한다.
크게 어렵지 않다.
이외에도 열거 상수의 이름을 투입하면 열거상수를 반환하는 valueOf() 등의 메서드가 있다.
끝!