티스토리 뷰
728x90
반응형
확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라
- 열거 타입 자체는 확장할 수 없지만, 인터페이스와 인터페이스를 구현하는 열거 타입을 통해 시너지를 낼 수 있습니다.
💡 타입 안전 열거 타입
- JDK 1.5 이전에 Enum이 없을 때 사용하던 방식입니다.
@ToString
public class Direction {
private final String location;
public static final Direction NORTH = new Direction("NORTH");
public static final Direction SOUTH = new Direction("SOUTH");
public static final Direction EAST = new Direction("EAST");
public static final Direction WEST = new Direction("WEST");
public Direction(String location) {
this.location = location;
}
}
💡 열거 타입
- 열거 타입은 거의 대부분의 상황에서 타입 안전 열거 패턴보다 우수합니다.
- 하지만 타입 안전 열거 패턴은 확장할 수 있으나 열거 타입은 확장할 수 없습니다.
- 연산 코드에서 API가 제공하는 기본 연산 이외에 추가적으로 다른 연산이 필요한 경우에는 확장할 수 있지만 대부분의 상황에서 열거 타입을 확장하는 것은 좋지 않습니다.
- 열거 타입을 확장하면 확장한 타입의 원소는 기반 타입의 원소로 취급하지만 그 반대는 성립하지 않을 수 있습니다. 말이 조금 어렵게 느껴질 수 있는데 상속받은 자식 원소의 뿌리는 부모의 원소이지만 그 반대는 성립하지 않는다는 말입니다.
- 열거 타입을 확장하면 기반 타입과 확장 타입들의 원소 모두를 순회할 방법이 마땅치 않습니다.
- 열거 타입을 확장할려면 열거 타입이 임의의 인터페이스를 구현하여 확장할 수 있습니다.(좋지는 않음)
enum Direction {
NORTH, SOUTH, EAST, WEST;
}
💡 인터페이스를 통해 확장한 열거 타입 1
- Enum 자체는 확장할 수 없지만 인터페이스를 통해 확장할 수 있습니다.
public interface Operation {
double apply(double x, double y);
}
public enum BasicOperation implements Operation {
PLUS("+") {
@Override
public double apply(double x, double y) {
return x + y;
}
},
MINUS("-") {
@Override
public double apply(double x, double y) {
return x - y;
}
},
TIMES("*") {
@Override
public double apply(double x, double y) {
return x * y;
}
},
DIVIDE("/") {
@Override
public double apply(double x, double y) {
return x / y;
}
};
private final String symbol;
BasicOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
💡 인터페이스를 통해 확장한 열거 타입 2
public enum ExtendedOperation implements Operation {
EXP("^") {
@Override
public double apply(double x, double y) {
return Math.pow(x, y);
}
},
REMAINDER("%") {
@Override
public double apply(double x, double y) {
return x % y;
}
};
private final String symbol;
ExtendedOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString() {
return symbol;
}
}
예시
💡 한정적 타입 토큰을 이용한 방법
- test 메서드에 인수로 ExtendedOperation의 class 리터럴을 넘겨 이용한 방식입니다.
- <T extends Enum<T> & Operation> 매개변수의 선언은 Class 객체가 열거 타입인 동시에 Operation 인터페이스의 구현체여야 한다는 의미입니다.
public class EffectiveJavaApplication {
public static void main(String[] args) throws Exception {
double x = 4;
double y = 2;
test(ExtendedOperation.class, x ,y);
}
private static <T extends Enum<T> & Operation> void test(Class<T> enumType, double x, double y) {
for (Operation o : enumType.getEnumConstants()) {
System.out.printf("%f %s %f = %f%n", x, o, y, o.apply(x, y));
// 4.000000 ^ 2.000000 = 16.000000
// 4.000000 % 2.000000 = 0.000000
}
}
}
💡 한정적 와일드 카드 타입을 이용한 방법
- 위의 예제보다 코드가 덜 복잡해지고 유연해졌습니다.
- 특정 연산에서 EnumMap이나 EnumSet을 사용할 수 없다는 단점이 있습니다.
public class EffectiveJavaApplication {
public static void main(String[] args) throws Exception {
double x = 4;
double y = 2;
testV2(Arrays.asList(ExtendedOperation.values()), x ,y);
}
private static void testV2(Collection<? extends Operation> operations, double x, double y) {
for (Operation o : operations) {
System.out.printf("%f %s %f = %f%n", x, o, y, o.apply(x, y));
// 4.000000 ^ 2.000000 = 16.000000
// 4.000000 % 2.000000 = 0.000000
}
}
}
💡 정리
- 열거 타입 자체는 확장할 수 없지만 인터페이스를 사용해 확장할 수 있습니다.
- 열거 타입끼리는 확장할 수 없다는 점을 인지해야하며, 디폴트 메서드는 안되고 인터페이스를 구현한 열거 타입 모두에 정의된 메서드가 들어가야 합니다.
728x90
반응형
'스터디 > 이펙티브 자바' 카테고리의 다른 글
이펙티브 자바 - Item40. @Override 애너테이션을 일관되게 사용하라 (0) | 2022.07.29 |
---|---|
이펙티브 자바 - Item39. 명명패턴보다 애너테이션을 사용하라. (0) | 2022.07.28 |
이펙티브 자바 - Item36. 비트 필드 대신 EnumSet을 사용하라. (0) | 2022.07.25 |
이펙티브 자바 - Item35. ordinal 메서드 대신 인스턴스 필드를 사용하라. (0) | 2022.07.25 |
이펙티브 자바 - Item34. int 상수대신 열거 타입을 사용하라. (0) | 2022.07.24 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- java userThread와 DaemonThread
- transactional outbox pattern spring boot
- 자바 백엔드 개발자 추천 도서
- pipeline architecture
- JDK Dynamic Proxy와 CGLIB의 차이
- spring boot poi excel download
- 레이어드 아키텍처란
- spring boot redis 대기열 구현
- spring boot redisson destributed lock
- spring boot excel download oom
- 람다 표현식
- pipe and filter architecture
- spring boot 엑셀 다운로드
- spring boot redisson sorted set
- 트랜잭셔널 아웃박스 패턴 스프링 부트 예제
- redis 대기열 구현
- 공간 기반 아키텍처
- redis sorted set
- polling publisher spring boot
- spring boot redisson 분산락 구현
- @ControllerAdvice
- 트랜잭셔널 아웃박스 패턴 스프링부트
- transactional outbox pattern
- spring boot excel download paging
- redis sorted set으로 대기열 구현
- service based architecture
- 서비스 기반 아키텍처
- java ThreadLocal
- microkernel architecture
- space based architecture
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함