Java Enum 메서드-반대 방향 enum 반환


113

반대 방향을 반환하는 메서드가있는 열거 형 Direction을 선언하고 싶습니다. 이것이 자바에서 가능합니까?

다음은 코드입니다.

public enum Direction {

     NORTH(1),
     SOUTH(-1),
     EAST(-2),
     WEST(2);

     Direction(int code){
          this.code=code;
     }
     protected int code;
     public int getCode() {
           return this.code;
     }
     static Direction getOppositeDirection(Direction d){
           return new Direction(d.getCode() * -1);
     }
}

스위치를 사용하십시오. 케이스는 4 개뿐입니다.
Sotirios Delimanolis

12
그런데, d.getCode() * -1==-d.getCode()
tckmn

Bloch의 Effective Java 6 장 (적어도 2E) 이 흥미로울 수 있으며 적극 권장됩니다.
jedwards

ntu.edu.sg/home/ehchua/programming/java/javaenum.html , 2.1 깔끔하게 개념을 설명하고있다
vikramvi

답변:


206

여기 제목으로 유혹하는 사람들을 위해 : 예, 열거 형에서 자신 만의 메서드를 정의 할 수 있습니다. 이러한 비 정적 메서드를 호출하는 방법이 궁금하다면 다른 비 정적 메서드와 동일한 방식으로 수행합니다. 해당 메서드를 정의하거나 상속하는 유형의 인스턴스에서 호출합니다. 열거 형의 경우 이러한 인스턴스는 단순히 ENUM_CONSTANTs입니다.

따라서 필요한 것은 EnumType.ENUM_CONSTANT.methodName(arguments).


이제 질문에서 문제로 돌아 갑시다. 해결책 중 하나는

public enum Direction {

    NORTH, SOUTH, EAST, WEST;

    private Direction opposite;

    static {
        NORTH.opposite = SOUTH;
        SOUTH.opposite = NORTH;
        EAST.opposite = WEST;
        WEST.opposite = EAST;
    }

    public Direction getOppositeDirection() {
        return opposite;
    }

}

지금 Direction.NORTH.getOppositeDirection() 반환 Direction.SOUTH됩니다.


@jedwards 주석 을 설명하는 좀 더 "해키"방식이 있지만 필드를 더 추가하거나 순서를 변경하면 코드가 깨지기 때문에 첫 번째 접근 방식만큼 유연하지 않습니다.

public enum Direction {
    NORTH, EAST, SOUTH, WEST;

    // cached values to avoid recreating such array each time method is called
    private static final Direction[] VALUES = values();

    public Direction getOppositeDirection() {
        return VALUES[(ordinal() + 2) % 4]; 
    }
}

3
나는 재빨리 준비하고 있었다 .values()[ordinal()]해킹을하지만,이 방법은 훨씬 더 강력
jedwards

그래도 어떻게 사용합니까? 이 기술은 무엇이라고 부릅니까?
Thufir

1
@Thufir " how do you use it "만약 당신이 메소드에 대해 묻는다면 다른 메소드처럼-당신은이 메소드로 클래스의 인스턴스에서 그것을 호출합니다. 의 인스턴스 Direction열거 클래스는 NORTH, EAST, SOUTH, WEST당신은 그냥 사용할 수 있도록 NORTH.getOppositeDirection()하며 반환합니다 SOUTH. " 라고?이 기술이 무엇인지 당신에 대해 물어 보는 경우는" static{...}다음은 정적 초기화 블록 이 코드는 클래스가 처음로드 될 때 (이것은 정적 필드를 초기화 동일한 프로세스의 일부) 호출이다.
Pshemo

@Pshemo, 정적 블록에 설정되는 값을 속성 파일에서 주입 해야하는 경우 위 코드의 Spring 버전이 어떻게 될지 궁금합니다.
Vikas Prasad

162

이와 같은 작은 열거 형의 경우 가장 읽기 쉬운 솔루션은 다음과 같습니다.

public enum Direction {

    NORTH {
        @Override
        public Direction getOppositeDirection() {
            return SOUTH;
        }
    }, 
    SOUTH {
        @Override
        public Direction getOppositeDirection() {
            return NORTH;
        }
    },
    EAST {
        @Override
        public Direction getOppositeDirection() {
            return WEST;
        }
    },
    WEST {
        @Override
        public Direction getOppositeDirection() {
            return EAST;
        }
    };


    public abstract Direction getOppositeDirection();

}

8
좋은 생각입니다! 일반적으로 각 열거 형 값이 특정 동작을 갖기를 원할 때도 좋습니다.
OferBr 2014-06-09

28

이것은 작동합니다 :

public enum Direction {
    NORTH, SOUTH, EAST, WEST;

    public Direction oppose() {
        switch(this) {
            case NORTH: return SOUTH;
            case SOUTH: return NORTH;
            case EAST:  return WEST;
            case WEST:  return EAST;
        }
        throw new RuntimeException("Case not implemented");
    }
}

8
null을 반환하는 대신 적절한 RuntimeException을 throw하는 기본 절은 새로 추가 된 방향에 대해 반대를 정의하지 않는 프로그래머 오류가 있음을 나타내는 것이 더 좋습니다.
Timothy055

1
이를 위해서는 호출자가 null을 처리해야합니다. 또한 관리자는 새 방향 유형이 추가 될 때마다 케이스를 추가해야합니다. 각 열거 형 값으로 재정의 할 수있는 추상 메서드를 사용하는 방법에 대한 Amir Afghani의 답변을 참조하십시오. 이렇게하면 값을 놓칠 위험이 없으며 null 처리에 대해 걱정할 필요가 없습니다.
Michael Peterson

14

추상 메서드를 만들고 각 열거 형 값이이를 재정의하도록합니다. 생성하는 동안 그 반대를 알고 있으므로 동적으로 생성하거나 생성 할 필요가 없습니다.

그래도 잘 읽히지는 않습니다. 아마도 switch더 관리하기 쉬울까요?

public enum Direction {
    NORTH(1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.SOUTH;
        }
    },
    SOUTH(-1) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.NORTH;
        }
    },
    EAST(-2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.WEST;
        }
    },
    WEST(2) {
        @Override
        public Direction getOppositeDirection() {
            return Direction.EAST;
        }
    };

    Direction(int code){
        this.code=code;
    }
    protected int code;

    public int getCode() {
        return this.code;
    }

    public abstract Direction getOppositeDirection();
}

4

예, 우리는 항상 그것을합니다. 새 개체가 아닌 정적 인스턴스를 반환합니다.

 static Direction getOppositeDirection(Direction d){
       Direction result = null;
       if (d != null){
           int newCode = -d.getCode();
           for (Direction direction : Direction.values()){
               if (d.getCode() == newCode){
                   result = direction;
               }
           }
       }
       return result;
 }

0
public enum Direction {
    NORTH, EAST, SOUTH, WEST;

    public Direction getOppositeDirection(){
        return Direction.values()[(this.ordinal() + 2) % 4];
    }
}

열거 형에는 선언 된 순서대로 열거 형의 모든 값을 포함하는 배열을 반환하는 정적 값 메서드가 있습니다. 출처

NORTH는 1, EAST는 2, SOUTH는 3, WEST는 4를 얻습니다. 간단한 방정식을 만들어 반대의 방정식을 얻을 수 있습니다.

(값 + 2) % 4


2
이것이 왜 답입니까? 이것이 미래의 독자 나 그 문제에 대한 누군가가 설명없이 배우는 데 어떻게 도움이 될 것으로 기대합니까?
GrumpyCrouton

이 코드가 질문에 답할 수 있지만 문제를 해결하는 방법 및 / 또는 이유에 대한 추가 컨텍스트 를 제공 하면 답변의 장기적인 가치가 향상됩니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오! 답변을 수정하여 설명을 추가하고 적용되는 제한 및 가정에 대한 표시를 제공하십시오. 이 답변이 다른 답변보다 더 적절한 이유를 언급하는 것도 나쁘지 않습니다.
ItamarG3

주석없이 코드를 읽는 것이 어렵습니까? 또는 7 줄의 코드 전용 javadoc이 필요합니까?
Pregunton

1
이 솔루션은 열거 형 값의 순서에 따라 달라지기 때문에 깨지기 쉽습니다. 알파벳순으로 순서를 변경하면 영리한 방정식이 더 이상 올바른 반대를 제공하지 않습니다.
Josh J
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.