ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 - 열거형(enums)
    언어/JAVA 2023. 3. 26. 16:51

    1. 열거형이란?

    - 열거형은 서로 관련된 상수를 묶어놓은 것이다. java의 열거형은 타입도 관리하여 타입에 안전한 열거형이다.

    - 마치 인스턴스가 미리 정의된 클래스로 생각해 볼 수 있다.

     

    1.2 열거형의 정의와 사용 

     

    - enum 열거체명 {상수명1,상수명2..} 등으로 정의할 수 있다.

    - 선언 위치는 클래스와 동일하다. 클래스 내부, 외부, 혹은 하나의 클래스파일에 정의할 수 있다.

    - 사용법은 열거체 참조변수에 열거체.상수명 혹은 열거형체.valueOf(상수명)

    - 모든 열거형의 조상 Enum에 Enum에 기본적으로 사용가능한 메서드들이 정의되어 있다. 

     

    enum Direction {EAST,SOUTH,WEST,NORTH}
    
     Direction dir = Direction.EAST;
     Direction dir2 = Direction.valueOf("SOUTH");

    출처: https://nathanh.tistory.com/118

    1.3 열거형에 멤버 추가하기 

     

    - 열거형 멤버에 여러 값을 할당 할 수 있다. 

    - 이때 열거형 멤버들은 미리 선언된 인스턴스와 같고, 열거형 내부에서 인스턴스를 생성하기 위한 생성자 및 메서드를 정의 해야한다. (내부적으로 사용되는 생성자와 변수는 private)

     

    enum Direction {
        EAST(1,">"),SOUTH(2,"v"),WEST(3,"<"),NORTH(4,"^");
        private final int value;
        private final String symbol;
        
       private Direction(int value,String symbol){
            this.value= value;
            this.symbol = symbol;
        }
        
        public int getValue() {return this.value;}
    
    }

    1.4 추상 메서드 추가하기 

     

    - 열거형에 추상메서드를 추가해서 열거형 멤버들이 이를 오버라이딩하게 할 수 있다.

    - 이는 마치 추상클래스를 상속받은 클래스가 오버라이딩하는 것과 같다. 

    - 각 열거체의 상수별로 오버라이딩을 통해 메서드 내용을 다르게 설정할 수 있다.

     enum Direction {
            EAST(1,">"){
                @Override
                int fare() {
                    return EAST.getValue()*2;
                }
            },SOUTH(2,"v") {
                @Override
                int fare() {
                    return SOUTH.getValue()+Basic_fare;
                }
            },WEST(3,"<") {
                @Override
                int fare() {
                    return WEST.getValue()+Basic_fare;
                }
            },NORTH(4,"^") {
                @Override
                int fare() {
                    return NORTH.getValue()+Basic_fare;
                }
            };
            private final int value;
            private final String symbol;
    
           protected final int Basic_fare=2; //protected로 해야 각 열거형 멤버들이 모두 접근 가능
           private Direction(int value,String symbol){
                this.value= value;
                this.symbol = symbol;
            }
            abstract int fare();
            public int getValue() {return this.value;}
        }

     

    2. 열거형의 이해

     

    열거형에 대한 더 싶은 이해를 위해 내부 구현에 대해 간단하게 살펴보자

     

    enum Direction {EAST,SOUTH,WEST,NORTH}는 아래 코드와 같다. 

     

    class Direction{
        static final Direction EAST = new Direction("EAST");
        static final Direction SOUTH = new Direction("SOUTH");
        static final Direction WEST = new Direction("WEST");
        static final Direction NORTH = new Direction("NORTH");
        
        private String name;
        private Direction(String name) {
            this.name=name;
        }
    }

    - static 상수 열거형 객체 EAST,SOUTH,WEST,NORTH는 객체의 주소를 담고 있고, 이 값은 바뀌지 않으므로 ==로 비교 가능

    - 또한 static 상수이므로 열거형이름.EAST등으로 사용가능한 것이다.

     

    abstract class MyEnum<T extends MyEnum<T>> implements Comparable<T>{
        static int id=0;
        int ordinal;
        String name ="";
        
        public int ordinal(){return ordinal;}
        MyEnum(String name){
            this.name = name;
            ordinal = id++;
        }
        public int compareTo(T t){
            return ordinal - t.ordinal();
        }
        
        
    }
    abstract class MyTransportation extends MyEnum{
        static final MyTransportation BUS = new MyTransportation("BUS",100) {
            int fare(int distance) {return distance * BASIC_FARE;
            }
        };
        static final MyTransportation TRAIN = new MyTransportation("TRAIN",100) {
            int fare(int distance) {return distance * BASIC_FARE;
            }
        };
        static final MyTransportation SHIP = new MyTransportation("SHIP",100) {
            int fare(int distance) {return distance * BASIC_FARE;
            }
        };
        static final MyTransportation AIRPLANE = new MyTransportation("AIRPLANE",100) {
            int fare(int distance) {return distance * BASIC_FARE;
            }
        };
        
        abstract int fare(int distance);
        protected final int BASIC_FARE;
        private MyTransportation(String name, int basicfare) {
            super(name);
            BASIC_FARE = basicfare;
        }
        public String name(){return name;}
        
    }
    

     - 객체가 생성될 때마다 ordinal에 저장

    - <T enxtends MyEnum<T>> 타입 T가 MyEnum<T>의 자손이어야 한다는 의미 (compareTo에서 t.ordinal()때문에 이렇게함) 

    - 추상메서드를 추가하면, 클래스 앞에 abstract 각 static 멤버들 익명클래스 형태로 추상메서드 구현

     

    **여기서 MyEnum<T> <- 이 <T>는 큰 의미는 없다.

    T extedns MyEnum인 것과 마찬가지 -> 제네릭 클래스에서 타입변수의 다형성 x (원시타입은 다형성 인정, 타입변수는 안됨)

    따라서 MyEnum<String,Integer...등등 뭐던 간에> T는 MyEnum<> 혹은 그 자손만 담을 수 있다.

     

     

    참고자료- 자바의 정석 남궁성 저 

     

Designed by Tistory.