가장 좋은 방법
package com.springandjava.Test.effectivejava.chatper6.item34;
public enum PayrollDay {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY(PayType.WEEKEND), SUNDAY(PayType.WEEKEND);
private final PayType payType;
PayrollDay(PayType payType) {
this.payType = payType;
}
int pay(int minutesWorked, int payRate) {
return payType.pay(minutesWorked, payRate);
}
//전략 열거 타입
enum PayType {
WEEKDAY {
int overtimePay(int minsWorked, int payRate) {
return minsWroked <= MINS_PER_SHIFT ? 0:
(minsWorked - MINS_PER_SHIFT) * payRate / 2;
}
},
WEEKEND {
};
abstract int overtimePay(int mins, int payRate);
private static final int MINS_PER_SHIFT = 8 * 60;
}
}
열거타입을 쓰는 경우?
Ordinal 메서드?
잘못된 방법
public enum Ensemble {
SOLO, DUET
public int numberofMusicians(){
return ordinal() + 1;
}
}
ordinal 메서드를 이용하게 되면 열거 순서가 바뀌는 경우, 상수 추가, 중간에 값을 비워둘 수가 없다
해결책
public enum Ensemble {
SOLO(1), DUET(2), TRIO(3);
private final int numberOfMusicians;
Ensemble(int size){
this.numberOfMusicians = size;
}
public int numberOfMusicians(){
return numberOfMusicians;
}
}
public class Text_old {
public static final int STYLE_BOLD = 1 << 0;
public static final int STYLE_ITALIC = 1 <<1;
public void applyStyles(int styles){};
}
다음과 같이 비트별 OR을 사용해서 여러 상수를 하나의 집함으로 모으며, 이렇게 만들어진 집합을 비트 필드라 한다 → 이렇게 작서하게되면 해석하기가 어려움
import java.util.Set;
public class Enumset {
public enum Style {BOLD, ITALIC, UNDERLINE, STRIKETHROUGH}
public void applyStyles(Set<Style> styles){}
}
EnumSet.of(Style.BOLD, Style.Italic)
다음과 같이 현대적 기법을 사용해서 EnumSet을 수정
EnumMap(EnumSet) 쓰면 좋을까? (vs HashMap)
public enum Phase {
SOLID, LIQUID, GAS;
public enum Transition {
MELT(SOLID, LIQUID);
private final Phase from;
private final Phase to;
Transition(Phase from, Phase to){
this.from = from;
this.to = to;
}
private static final Map<Phase, Map<Phase, Transition>>
m = Stream.of(values()).collect(groupingBy(t -> t.from, ()-> new EnumMap<>(Phase.class),
toMap(t ->t.to, t -> t,(x,y) -> y, () -> new EnumMap<>(Phase.class))));
public static Transition from(Phase from, Phase to){
return m.get(from).get(to);
}
}
}
//인터페이스를 정의하고
public interface Operation {
double apply (double x, double y);
}
//인터페이스를 구현하면서 enum확장이 가능
public enum BasicOperation implements Operation{
PLUS("+") {
@Override
public double apply(double x, double y) {
return x + y;
}
};
private final String symbol;
//this.symbol = 이 클래스 기반으로 생성된 인스턴스 // 매개변수, 맴버변수와 이름 구별
BasicOperation(String symbol) {
this.symbol = symbol;
}
@Override
public String toString(){
return symbol;
}
}
인터페이스를 선언하고 해당 인터페이스를 구현하는 enum 클래스를 만듦으로서 enum확장이 가능한 것처럼 구현할 수 있다.
명명패턴의 단점
//Test가 런타임에도 유지되도록 하게끔 선언하는 에너테이션
@Retention(RetentionPolicy.RUNTIME)
//Test가 반드시 메서드에 선언에서만 사용된다고 알려줌
@Target(ElementType.METHOD)
public @interface Test {
}
@Override 는 매서드 선언에서만 달 수 있으며, 이 애너테이션은이 달렸다는 것은 상위 타입의 매서드를 재정의 했음을 뜻한다
재저으이한 모든 매서드에 @Override 어노테이션을 달게되면 컴파일라가 잘못된 오류를 자동적으로 잡아자ㅜㄹ 것이다
아무 메서드도 없고, 자신을 구현하는 클래스가 특정 속성을 갖고 있음을 표시해줄 경우
→ 마커 인터페이스를 사용
마커인터페이스가 마커 애너테이션보다 나은 이유
적용 대상이 ElementType.TYPE인 애너테이션을 작성하고 있다면 마커인터페이스도 고려해라