JAVA/Effective Java

Enum - 규칙 34 확장 가능한 enum을 만들어야 한다면 인터페이스를 이용하라.

반응형

연산자를 정의해둔 Enum을 사용할 때 더많은 유형의 자료형을 사용하기 위해서 
기존의 enum객체를 계승해서 작성하고 싶을 수 있다.

하지만 enum 자료형은 계승해서 사용하는 방법은 어렵다.

왜냐하면 모든 Enum 객체들은 함축적으로 Enum 객체를 상속받고 있다. 
자바에서는 클래스는 하나이상의 부모를 가질 수 없으므로, enum 객체는 추가 상속이 어렵다.

그렇기에 인터페이스를 먼저 구현하고 그에 맞게 enum을 구현할 수 있도록 인터페이스를 활용하는 방식으로 대처할 수 있다.



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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package effective34;
 
/**
 * 연산자를 정의해둔 인터페이스
 * 
 * @author wedul
 *
 */
public interface Operation {
    /**
     * 연산자별 동작을 구현한 메소드
     * 
     * @param x
     * @param y
     * @return
     */
    double apply(double x, double y);
    
    /**
     * symbol
     * 
     * @return
     */
    String getSymbol();
}
 
package effective34;
 
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 getSymbol() {
        return symbol;
    }
 
}
 
package effective34;
 
public enum ExtendedOperation implements Operation {
    EXP("^") {
        @Override
        public double apply(double x, double y) {
            return Math.pow(x,  y);
        }
    };
    
    private final String symbol;
    
    ExtendedOperation(String symbol) {
        this.symbol = symbol;
    }
    
    @Override
    public String getSymbol() {
        return this.symbol;
    }
}
cs



위와 같은 방식으로 구현하게 되면 다음과 같이 인터페이스만을 넘겨서 다양한 경우에서 사용할 수 있다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public static void main(String args[]) {
    double x = 10;
    double y = 30;
    getOperationResult(BasicOperation.class, x, y);
    getOperation2(ExtendedOperation.EXP, x, y);
}
    
/**
 * 전달받은 Enum 객체에 구현된 apply를 모두 실행
 * 
 * @param op
 * @param x
 * @param y
 */
private static <extends Enum<T> & Operation> void getOperationResult(Class<T> op, double x, double y) {
    for (Operation operation : op.getEnumConstants()) {
        System.out.println(operation.getSymbol() + " result : " + operation.apply(x, y));
    }
}
    
private static <extends Operation> void getOperation2(T op, double x, double y) {
    System.out.println(op.getSymbol() + " result : " + op.apply(x, y));
}
cs




결론
enum클래스는 내부적으로 Enum<T>를 상속받고 있기 때문에 다른 클래스를 extend 할 수 없다.
그렇기 때문에 enum의 기능을 계승해서 사용하고 싶은경우에는 interface를 만들어서 구현해서 사용해야 한다.

출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙34 인용.

반응형