1. Enum도 사실은 클래스다
우리가 흔히 쓰는 Enum은 사실 특별한 클래스다.
public enum PaymentType {
CARD, BANK, KAKAO
}
이 코드는 내부적으로 이렇게 동작한다
public class PaymentType {
public static final PaymentType CARD = new PaymentType();
public static final PaymentType BANK = new PaymentType();
public static final PaymentType KAKAO = new PaymentType();
private PaymentType() {} // private 생성자
}
그래서 Enum도 클래스처럼 필드와 메서드를 가질 수 있다.
2. Enum 본체란 ?
Enum은 두 부분으로 나뉜다
- 상수 선언부 (위쪽)
- 본체 (아래쪽)
public enum PaymentType {
// ========== 1. 상수 선언부 ==========
CARD, BANK, KAKAO; // 세미콜론(;)으로 끝
// ========== 2. Enum 본체 ==========
// 여기서부터는 일반 클래스처럼 메서드를 정의할 수 있다
public void printType() {
System.out.println("결제 타입: " + this.name());
}
public String getDescription() {
return "결제 수단";
}
}
상수 선언이 끝나면 세미콜론(;)을 찍고 그 다음부터가 "본체"다.
3. 각 상수마다 다른 동작이 필요하다면?
만약 CARD, BANK, KAKAO가 각각 다른 결제 프로세서를 생성해야 한다면?
방법 1: switch문 사용 (별로 안 좋음)
public enum PaymentType {
CARD, BANK, KAKAO;
public PaymentProcessor createProcessor() {
switch(this) {
case CARD:
return new CardPaymentProcessor();
case BANK:
return new BankPaymentProcessor();
case KAKAO:
return new KakaoPaymentProcessor();
default:
throw new IllegalArgumentException();
}
}
}
문제점 새 결제 수단 추가 시 switch문을 수정해야 한다. (OCP 위반)
방법 2: 추상 메서드 사용 (추천!)
public enum PaymentType {
// ========== 상수 선언부 ==========
CARD {
@Override
public PaymentProcessor createProcessor() {
return new CardPaymentProcessor();
}
},
BANK {
@Override
public PaymentProcessor createProcessor() {
return new BankPaymentProcessor();
}
},
KAKAO {
@Override
public PaymentProcessor createProcessor() {
return new KakaoPaymentProcessor();
}
}; // 마지막 세미콜론!
// ========== Enum 본체 ==========
public abstract PaymentProcessor createProcessor();
}
4. 각 상수의 중괄호의 의미
CARD {
@Override
public PaymentProcessor createProcessor() {
return new CardPaymentProcessor();
}
}
이 중괄호 {}는 익명 클래스(Anonymous Class) 문법이다.
실제로는 이렇게 동작한다.
public static final PaymentType CARD = new PaymentType() {
@Override
public PaymentProcessor createProcessor() {
return new CardPaymentProcessor();
}
};
CARD는 PaymentType을 상속받은 익명 클래스의 인스턴스다.
5. 추상 메서드 사용
에러상황
public enum PaymentType {
CARD, BANK, KAKAO; // 메서드 구현 안 함
public abstract PaymentProcessor createProcessor(); // 추상 메서드
}
컴파일 에러 발생!
Error: PaymentType.CARD is not abstract and does not override abstract method createProcessor()
컴파일러가 "CARD가 createProcessor() 구현 안 했어!"라고 알려준다.
컴파일 실수 방지
public enum PaymentType {
CARD {
@Override
public PaymentProcessor createProcessor() {
return new CardPaymentProcessor();
}
},
BANK {
@Override
public PaymentProcessor createProcessor() {
return new BankPaymentProcessor();
}
},
NAVER {
// 메서드 구현 깜빡함!
}; // ← 컴파일 에러!
public abstract PaymentProcessor createProcessor();
}
새 상수를 추가하고 메서드 구현을 깜빡하면 컴파일 에러가 난다.
런타임 에러가 아니라 컴파일 타임에 잡아준다!
6. 전체 구조 정리
public enum PaymentType {
// ===== 1단계: 각 상수가 메서드를 구현 =====
CARD {
@Override
public PaymentProcessor createProcessor() {
return new CardPaymentProcessor();
}
}, // 쉼표
BANK {
@Override
public PaymentProcessor createProcessor() {
return new BankPaymentProcessor();
}
}, // 쉼표
KAKAO {
@Override
public PaymentProcessor createProcessor() {
return new KakaoPaymentProcessor();
}
}; // 세미콜론! (마지막 상수 뒤)
// ===== 2단계: Enum 본체에 추상 메서드 선언 =====
public abstract PaymentProcessor createProcessor();
}
// ===== 3단계: 공통 인터페이스 정의 =====
interface PaymentProcessor {
void process(int amount);
}
// ===== 4단계: 각 프로세서 구현 =====
class CardPaymentProcessor implements PaymentProcessor {
public void process(int amount) {
System.out.println("카드 결제: " + amount);
}
}
class BankPaymentProcessor implements PaymentProcessor {
public void process(int amount) {
System.out.println("계좌이체: " + amount);
}
}
class KakaoPaymentProcessor implements PaymentProcessor {
public void process(int amount) {
System.out.println("카카오페이: " + amount);
}
}
7. 사용 예시
public class PaymentService {
public void pay(PaymentType type, int amount) {
// 각 타입이 자신만의 프로세서를 생성한다
PaymentProcessor processor = type.createProcessor();
processor.process(amount);
}
}
// 호출
PaymentService service = new PaymentService();
service.pay(PaymentType.CARD, 10000); // 출력: 카드 결제: 10000
service.pay(PaymentType.KAKAO, 5000); // 출력: 카카오페이: 5000
8. 핵심 정리
- Enum도 클래스다 - 메서드를 가질 수 있다
- 상수 선언부와 본체를 세미콜론(;)으로 구분한다
- 추상 메서드를 본체에 선언하면 각 상수가 반드시 구현해야 한다
- 각 상수의 중괄호는 익명 클래스 문법이다
- 컴파일 타임에 실수를 잡아준다 - 런타임 에러 방지
9. 사용하면 좋은 상황
- 각 상수마다 다른 동작이 필요할 때
- switch문을 없애고 싶을 때
- 새 타입 추가 시 컴파일러의 도움을 받고 싶을 때
- 타입 안정성을 확보하고 싶을 때
'공부일기.. > Java' 카테고리의 다른 글
| [디자인패턴] 자바 전략 패턴(Strategy Pattern) (0) | 2025.11.25 |
|---|---|
| [java] 예외 처리와 트랜잭션 롤백 (PSA (Portable Service Abstraction)) (0) | 2025.10.29 |
| [코테] JAVA 백준 알고리즘 시작하기 - 입출력 가이드 !!성능최적화!! (0) | 2025.09.29 |
| [java] 자바 파일 처리 기본기 가이드 - 주니어 개발자 필수 FILE/FILES (0) | 2025.09.22 |
| [java] static 제대로 활용하기 - 패턴과 함정 (0) | 2025.09.21 |