TIL

아이템34. int 상수 대신 열거 타입을 사용하라

자바가 열거 타입을 지원하기 전

로또의 등수를 표현한다고 가정해보자. 열거 타입을 쓸 수 없다면 다음과 같이 표현할 수 있을 것이다.

public static final int LOTTO_RANK_FIRST = 1;
public static final int LOTTO_RANK_SECOND = 2;
public static final int LOTTO_RANK_THRID = 3;
public static final int LOTTO_RANK_FOURTH = 4;
public static final int LOTTO_RANK_FIFTH = 5;
public static final int LOTTO_RANK_NOTHING = 0;

1등은 정수 1로, 5등은 5로, 꽝은 0으로 정수를 열거하여 작성했다. 이렇게 정수 열거 패턴을 사용하면 단점이 많다.

열거 타입(enum type)

이제 로또 등수에 열거 타입을 적용하여 정수 열거 패턴의 단점을 어떻게 극복하는지 살펴보자.

public enum LottoRank {

	FIFTH(3, 5_000),
	FOURTH(4, 50_000),
	THIRD(5, 1_500_000),
	SECOND(5, 30_000_000),
	FIRST(6, 2_000_000_000),
	NOTHING(0, 0);

	private final int matchNumber;
	private final int prize;

	LottoRank(int matchNumber, int prize) {
		this.matchNumber = matchNumber;
		this.prize = prize;
	}
}

private static LottoRank checkSecondOrThird(boolean bonus) { if (bonus) { return LottoRank.SECOND; } return LottoRank.THIRD; }

즉 열거 타입은 단순한 상수 모음이 아니라 메서드를 추가하여 고차원의 추상 개념 하나를 완벽히 표현해낼 수도 있다.

### 상수마다 다른 동작 구현하기
상수마다 동작이 달라져야 하는 상황도 있을 것이다. 예를 들어 알바생에게 근로 수당을 챙겨주는 상황이라고 해보자. 주간 근무라면 '일한 시간 X 임금'만큼 주면 되지만, 야간 근무를 했을 경우 야간 수당으로 1.5배를 더 줘야 한다. 열거 타입으로 DAY_SHIFT와 NIGHT_SHIFT가 있을 때 다른 급여 산출 기준이 필요하다. 열거 타입을 사용하여 다음과 같이 구현할 수 있다.

```java
public enum PayrollDay {

	DAY_SHIFT(((time, wage) -> time * wage)),
	NIGHT_SHIFT((time, wage) -> time * wage * 1.5);

	private final PayType payType;

	PayrollDay(PayType payType) {
		this.payType = payType;
	}

	public double pay(int time, int wage) {
		return payType.pay(time, wage);
	}

	interface PayType {
		double pay(int time, int wage);
	}
}

직접 구현한 내부 인터페이스를 필드로 가지며 생성자에 인터페이스 구현체를 람다로 넣어주었다. 이렇게 하면 주간 근무와 야간 근무의 급여 산출이 달라질 수 있다.

double dayShiftPay = PayrollDay.DAY_SHIFT.pay(60, 10000); // 60_000
double nightShiftPay = PayrollDay.NIGHT_SHIFT.pay(60, 10000); // 90_000