코드에서 스위치를 제거하는 방법 [닫기]


175

코드에서 스위치를 사용하지 않는 방법은 무엇입니까?


18
적절하게 사용될 때 왜 스위치를 제거하고 싶습니까? 질문에 대해 자세히 설명해주세요.
RB.

모두가 같은 일을 말하고 있기 때문에 나는이 질문 할 지역 사회의 편집을 투표하고는 모든 의견을 통합하는 것이 좋을 수도 있습니다)
조쉬

2
스위치는 다른 지침만큼 표준이 아닙니다. 예를 들어 C ++에서는 '중단'을 잊어 버린 경우 예기치 않은 결과가 발생합니다. 게다가,이 '휴식'은 GOTO와 너무 비슷합니다. 나는 스위치를 제거하려고 시도한 적이 없지만, 내가 가장 좋아하는 명령은 아닙니다. ;)

2
그는 C ++ 또는 Java switch 문이 아니라 스위치 개념을 언급하고 있다고 생각합니다. 스위치는 'if-else if'블록 체인 일 수도 있습니다.
무법자 프로그래머

2
anti-IF 캠페인에 참여하는 민첩한 커뮤니티의 많은 프로그래머가 있습니다 : antiifcampaign.com/supporters.html
Mike A

답변:


267

스위치 문은 그 자체로 반 패턴이 아니지만 객체 지향을 코딩 하는 경우 스위치 문을 사용하는 대신 다형성 으로 스위치 사용을 더 잘 해결할 수 있는지 고려해야합니다 .

다형성을 사용하면 다음과 같습니다.

foreach (var animal in zoo) {
    switch (typeof(animal)) {
        case "dog":
            echo animal.bark();
            break;

        case "cat":
            echo animal.meow();
            break;
    }
}

이된다 :

foreach (var animal in zoo) {
    echo animal.speak();
}

2
stackoverflow.com/questions/374239/ 에서 비슷한 제안으로 인해 쫓겨났습니다. 많은 ppl은 다형성을 믿지 않습니다 :) 아주 좋은 예입니다.
Nazgob

30
-1 :와 함께 switch 문을 사용한 적이 없으며이 typeof답변에서는 다른 상황에서 switch 문을 해결하는 방법이나 이유를 제안하지 않습니다.
Kevin

3
@Kevin에 동의합니다. 주어진 예는 실제로 다형성으로 스위치를 제거하는 방법을 보여주지 않습니다. 간단한 예 : 값을 전환하여 열거 형의 이름을 얻거나 일종의 알고리즘에서 적절한 값으로 코드를 수행하십시오.
HotJard

특정 구현, 즉 공장에서 신뢰할 수 있기 전에 제거하는 방법이 궁금합니다. 그리고 여기에 훌륭한 예가 있습니다. stackoverflow.com/a/3434505/711855
juanmf

1
아주 사소한 예입니다.
GuardianX

239

스위치 선언문 냄새 참조 :

일반적으로 유사한 스위치 문이 프로그램 전체에 흩어져 있습니다. 하나의 스위치에서 절을 추가하거나 제거하면 다른 스위치도 찾아서 복구해야합니다.

리팩토링패턴 리팩토링 모두이 문제를 해결하는 방법이 있습니다.

(의사) 코드가 다음과 같은 경우

class RequestHandler {

    public void handleRequest(int action) {
        switch(action) {
            case LOGIN:
                doLogin();
                break;
            case LOGOUT:
                doLogout();
                break;
            case QUERY:
               doQuery();
               break;
        }
    }
}

이 코드는 공개 폐쇄 원칙을 위반하며 발생 하는 모든 새로운 유형의 조치 코드에 취약합니다. 이를 해결하기 위해 'Command'객체를 도입 할 수 있습니다.

interface Command {
    public void execute();
}

class LoginCommand implements Command {
    public void execute() {
        // do what doLogin() used to do
    }
}

class RequestHandler {
    private Map<Integer, Command> commandMap; // injected in, or obtained from a factory
    public void handleRequest(int action) {
        Command command = commandMap.get(action);
        command.execute();
    }
}

(의사) 코드가 다음과 같은 경우

class House {
    private int state;

    public void enter() {
        switch (state) {
            case INSIDE:
                throw new Exception("Cannot enter. Already inside");
            case OUTSIDE:
                 state = INSIDE;
                 ...
                 break;
         }
    }
    public void exit() {
        switch (state) {
            case INSIDE:
                state = OUTSIDE;
                ...
                break;
            case OUTSIDE:
                throw new Exception("Cannot leave. Already outside");
        }
    }

그런 다음 'State'객체를 소개 할 수 있습니다.

// Throw exceptions unless the behavior is overriden by subclasses
abstract class HouseState {
    public HouseState enter() {
        throw new Exception("Cannot enter");
    }
    public HouseState leave() {
        throw new Exception("Cannot leave");
    }
}

class Inside extends HouseState {
    public HouseState leave() {
        return new Outside();
    }
}

class Outside extends HouseState {
    public HouseState enter() {
        return new Inside();
    }
}

class House {
    private HouseState state;
    public void enter() {
        this.state = this.state.enter();
    }
    public void leave() {
        this.state = this.state.leave();
    }
}

도움이 되었기를 바랍니다.


7
코드를 리팩터링하는 방법에 대한 훌륭한 예를 주셔서 감사합니다. 비록 구걸에서 말할 수는 없지만 읽기가 조금 어렵습니다 (완전히 이해하기 위해 여러 파일간에 전환해야하기 때문에)
rshimoda

8
스위치에 대한 인수는 다형성 솔루션이 코드 단순성을 희생한다는 사실을 알고있는 한 유효합니다. 또한 스위치 케이스를 항상 열거 형으로 저장하면 일부 컴파일러는 스위치에서 상태가 누락되었음을 경고합니다.
Harvey

1
이것은 완료 / 불완전한 작업과 물론 OOP로 코드를 재구성하는 좋은 예입니다. 정말 감사합니다. OOP / Design Patterns 지지자들이 OOP 개념을 개념이 아닌 연산자로 취급하도록 제안 하면 도움이 될 입니다. "확장하다", "공장", "구현물"등은 파일, 클래스, 브랜치에서 자주 사용됩니다. "+", "-", "+ =", "? :", "==", "->"등과 같은 연산자로 단순해야합니다. 프로그래머가 단순히 연산자처럼 자신의 마음에 사용할 때 그런 다음 전체 클래스 라이브러리에서 프로그램 상태 및 (완료된) 작업에 대해 생각할 수 있습니다.
namespaceform

13
SWITCH가 이것에 비해 훨씬 이해하기 쉽고 논리적이라고 생각하기 시작했습니다. 그리고 나는 보통 OOP를 매우 좋아하지만이 해상도는 나에게는 너무 추상적 인 것 같습니다
JK

1
Command 객체를 사용하면 생성하는 코드에 Map<Integer, Command>스위치가 필요하지 않습니까?
ataulm

41

스위치는 스위치 문으로 구현되는지 여부에 관계없이 체인, 룩업 테이블, oop 다형성, 패턴 일치 또는 다른 것입니다.

" switch statement "또는 " switch pattern "을 사용하지 않겠습니까? 첫 번째 것은 다른 패턴 / 알고리즘을 사용할 수있는 경우에만 제거 할 수 있으며, 대부분 불가능하거나 더 나은 방법은 아닙니다.

코드 에서 switch 문 을 제거하려면 첫 번째 질문 은 switch 문을 제거하고 다른 기술을 사용 하는 것이 합리적 입니다. 불행히도이 질문에 대한 답변은 도메인마다 다릅니다.

컴파일러는 명령문을 전환하기 위해 다양한 최적화를 수행 할 수 있습니다. 예를 들어, 메시지 처리를 효율적으로 수행하려면 switch 문을 사용하는 것이 좋습니다. 그러나 다른 한편으로는 switch 문을 기반으로 비즈니스 규칙을 실행하는 것이 가장 좋은 방법은 아니며 응용 프로그램을 재구성해야합니다.

switch 문에 대한 대안은 다음과 같습니다.


1
누군가가 스위치와 다른 대안을 사용하여 메시지 처리를 비교할 수 있습니까?
Mike A

37

스위치 자체는 그렇게 나쁘지는 않지만 메서드의 객체에 "스위치"또는 "if / else"가 많은 경우 디자인이 약간 "절차 적"이고 객체가 가치가 있다는 신호일 수 있습니다 양동이. 논리를 객체로 옮기고 객체에서 메소드를 호출 한 다음 대신 응답 방법을 결정하도록합니다.


물론 그가 C로 작성하지 않았다고 가정 :)
Bernard

1
C에서는 함수 포인터와 구조체를 사용하여 객체와 같은 것을 만들 수 있습니다.)
Tetha

모든 언어로 FORT ^ H ^ H ^ H ^ H Java를 작성할 수 있습니다. ; p
Bernard

완전히 동의하십시오-스위치는 코드 줄을 줄이는 좋은 방법이지만 너무 많이 사용하지는 마십시오.
HotJard

21

가장 좋은 방법은 좋은지도를 사용하는 것입니다. 사전을 사용하면 거의 모든 입력을 다른 값 / 객체 / 함수에 매핑 할 수 있습니다.

코드는 다음과 같이 보일 것입니다.

void InitMap(){
    Map[key1] = Object/Action;
    Map[key2] = Object/Action;
}

Object/Action DoStuff(Object key){
    return Map[key];
}

4
언어에 따라 다릅니다. 스위치보다 훨씬 읽기
어려울 수

이것은 올바른 상황에서 좋은 elegent 솔루션입니다. 최근 에이 매핑 키 코드를 수행했으며 그 목적에 맞는 것으로 보였습니다.
Bernard

이것은 사실입니다. 아마도 이것을 간단한 용도로 사용하지는 않지만 스위치 문을 통한 구성 측면에서 약간의 유연성을 제공합니다. 스위치는 항상 하드 코딩되는 동안 사전을 즉석에서 준비 할 수 있습니다.
Josh

어떤 상황에서는 더 깨끗할 수 있습니다. 함수 호출이 필요하기 때문에 느려집니다.
Nick Johnson

1
그것은 당신의 열쇠에 달려 있습니다. 컴파일러는 스위치 호출 문을 함수 호출없이 간단한 조회 또는 매우 빠른 정적 이진 검색으로 컴파일 할 수 있습니다.
Nick Johnson

12

모두가 거대한 if else블록을 좋아 합니다. 너무 쉽게 읽을 수 있습니다! 그래도 스위치 문을 제거하려는 이유가 궁금합니다. switch 문이 필요한 경우 switch 문이 필요할 수 있습니다. 진지하게, 나는 그것이 코드가하는 일에 달려 있다고 말합니다. 모든 스위치가 함수를 호출하는 중이라면 함수 포인터를 전달할 수 있습니다. 더 나은 솔루션 인지 여부 는 논쟁의 여지가 있습니다.

언어도 여기서 중요한 요소라고 생각합니다.


13
나는 그것이 풍자라고 가정 :)
Craig Day

6

나는 당신이 찾고있는 것이 전략 패턴이라고 생각합니다.

이것은 여러 가지 방법으로 구현 될 수 있으며, 다음과 같이이 질문에 대한 다른 답변에서 언급되었습니다.

  • 값의 맵-> 함수
  • 다형성. (객체의 하위 유형은 특정 프로세스를 처리하는 방법을 결정합니다).
  • 일급 기능.

5

switch 명령문에 새로운 상태 또는 새로운 동작을 추가하면 명령문을 대체하는 것이 좋습니다.

int 상태;

문자열 getString () {
   스위치 (상태) {
     case 0 : // 상태 0에 대한 동작
           "제로"를 반환;
     case 1 : // 상태 1의 동작
           "하나"를 반환;
   }
   새로운 IllegalStateException () 던지기;
}

이중 getDouble () {

   스위치 (this.state) {
     case 0 : // 상태 0에 대한 동작
           리턴 0d;
     case 1 : // 상태 1의 동작
           1d를 반환;
   }
   새로운 IllegalStateException () 던지기;
}

새로운 동작을 추가하려면을 복사해야하며 switch새로운 상태를 추가 case하면 모든 switch 명령문에 다른 상태를 추가 해야 합니다.

Java에서는 런타임시 값을 알고있는 매우 제한된 수의 기본 유형 만 전환 할 수 있습니다. 이것은 그 자체로 문제를 제시합니다 : 상태는 마법의 숫자 나 문자로 표현됩니다.

if - else새로운 동작과 새로운 상태를 추가 할 때 실제로 동일한 문제가 있지만 패턴 일치 및 여러 블록을 사용할 수 있습니다.

다른 사람들이 "다형성 (polymorphism)"으로 제안한 솔루션은 State 패턴 의 인스턴스입니다 .

각 상태를 자체 클래스로 바꿉니다. 각 행동에는 클래스에 대한 자체 메소드가 있습니다.

국가 상태;

문자열 getString () {
   return state.getString ();
}

이중 getDouble () {
   return state.getDouble ();
}

새로운 상태를 추가 할 때마다 새로운 IState인터페이스 구현을 추가해야합니다 . switch세계 에서는 case각에를 추가 할 것 switch입니다.

새로운 행동을 추가 할 때 IState마다 인터페이스와 각 구현에 새로운 메소드를 추가해야합니다 . 이것은 컴파일러가 이전과 동일한 부담이지만, 이제 컴파일러는 기존의 각 상태에 대해 새로운 동작의 구현이 있는지 확인합니다.

다른 사람들은 이미 이것이 너무 무거울 수 있다고 말 했으므로 물론 당신이 서로 이동하는 지점에 도달 할 수 있습니다. 개인적으로 두 번째로 스위치를 작성할 때는 리팩터링하는 시점입니다.


4

다른 경우라면

나는 스위치가 본질적으로 나쁘다는 전제를 반박한다.


3

글쎄, 나는 스위치를 사용하는 것이 안티 패턴이라는 것을 몰랐다.

둘째, 스위치는 항상 if / else if 문으로 대체 될 수 있습니다.


정확히-스위치는 if / elsifs에 대한 구문 메타 데이터입니다.
Mike A

3

왜하고 싶니? 좋은 컴파일러의 경우 switch 문은 if / else 블록보다 훨씬 효율적일뿐만 아니라 읽기가 더 쉬울 수 있으며, 가장 큰 스위치 만 다른 유형으로 교체되면 속도가 빨라질 수 있습니다. 간접 조회 데이터 구조


2
어느 시점에서 컴파일러를 다시 추측하고 컴파일러 내부를 기반으로 디자인을 변경합니다. 디자인은 컴파일러의 본질이 아니라 문제의 본질을 따라야합니다.
Mike A

3

'스위치'는 언어 구성 일 뿐이며 모든 언어 구성은 작업을 수행하기위한 도구로 생각할 수 있습니다. 실제 도구와 마찬가지로 일부 도구는 다른 도구보다 한 작업에 더 적합합니다 (그림 고리를 걸기 위해 썰매 망치를 사용하지 않음). 중요한 부분은 '작업 완료'가 어떻게 정의되는지입니다. 유지 관리가 가능해야하고, 빠르거나, 확장이 필요하고, 확장 가능해야 하는가 등이 있습니다.

프로그래밍 프로세스의 각 지점에는 일반적으로 스위치, if-else-if 시퀀스, 가상 함수, 점프 테이블, 함수 포인터가있는 맵 등 사용할 수있는 다양한 구문과 패턴이 있습니다. 경험이 있으면 프로그래머는 주어진 상황에 적합한 도구를 본능적으로 알게됩니다.

코드를 유지 관리하거나 검토하는 사람은 최소한 원본 작성자만큼 숙련되어 모든 구성을 안전하게 사용할 수 있다고 가정해야합니다.


그러나 조건부 실행과 같은 일을하는 5 가지의 다른 중복 방법이 필요한 이유는 무엇입니까?
Mike A

@ mike.amy : 각 방법마다 장점과 비용이 다르기 때문에 가장 적은 비용으로 최대한의 이익을 얻는 것이 중요합니다.
Skizz

1

다양한 종류의 객체를 구별하기 위해 스위치가있는 경우 해당 객체 또는 가상 메소드를 정확하게 설명하는 클래스가 누락되었을 수 있습니다.


1

C ++ 용

즉, AbstractFactory를 참조하는 경우 registerCreatorFunc (..) 메소드가 일반적으로 필요한 각각의 모든 "새"문에 대해 대소 문자를 추가하는 것보다 낫다고 생각합니다. 그런 다음 모든 클래스가 creatorFunction (..) 을 생성하고 등록 하게하여 매크로로 쉽게 구현할 수 있습니다. 나는 이것이 많은 프레임 워크가하는 일반적인 접근 방식이라고 생각합니다. 나는 먼저 ET ++에서 그것을 보았고 DECL과 IMPL 매크로가 필요한 많은 프레임 워크가 그것을 사용한다고 생각합니다.


1

C와 같은 절차 적 언어에서 스위치는 다른 대안보다 낫습니다.

객체 지향 언어에는 객체 구조, 특히 다형성을 더 잘 활용하는 다른 대안이 거의 항상 있습니다.

스위치 문의 문제는 응용 프로그램의 여러 위치에서 매우 유사한 여러 스위치 블록이 발생할 때 발생하며 새로운 값에 대한 지원이 추가되어야합니다. 개발자가 애플리케이션 주위에 흩어져있는 스위치 블록 중 하나에 새로운 값에 대한 지원을 추가하는 것을 잊어 버리는 것이 일반적입니다.

다형성을 사용하면 새 클래스가 새 값을 대체하고 새 클래스를 추가 할 때 새 동작이 추가됩니다. 그런 다음 이러한 스위치 지점에서의 동작은 수퍼 클래스에서 상속되거나 새로운 동작을 제공하도록 재정의되거나 수퍼 메소드가 추상 일 때 컴파일러 오류를 피하기 위해 구현됩니다.

명백한 다형성이 진행되지 않는 경우 전략 패턴을 구현할 가치가 있습니다 .

그러나 대안이 큰 IF ... THEN ... ELSE 블록이면 잊어 버려라.


1

내장 된 switch 문과 함께 제공되지 않는 언어를 사용하십시오. 펄 5가 떠오른다.

진지하게, 왜 피하고 싶습니까? 그것을 피해야 할 충분한 이유가 있다면, 왜 그렇게 피하지 않겠습니까?


1

함수 포인터는 거대한 chunky switch 문을 대체하는 한 가지 방법입니다. 특히 함수 이름으로 함수를 캡처하고 만들 수있는 언어에 적합합니다.

물론 코드에서 스위치 문을 강제로 실행해서는 안되며, 항상 모든 잘못된 일을 할 가능성이 있습니다. 이로 인해 어리석은 중복 코드가 생성됩니다. (이것은 때로는 피할 수 없지만 좋은 언어를 사용하면 깨끗하게 유지하면서 중복성을 제거 할 수 있습니다.)

이것은 훌륭한 분할 및 정복 예제입니다.

어떤 종류의 통역사가 있다고 가정하십시오.

switch(*IP) {
    case OPCODE_ADD:
        ...
        break;
    case OPCODE_NOT_ZERO:
        ...
        break;
    case OPCODE_JUMP:
        ...
        break;
    default:
        fixme(*IP);
}

대신 다음을 사용할 수 있습니다.

opcode_table[*IP](*IP, vm);

... // in somewhere else:
void opcode_add(byte_opcode op, Vm* vm) { ... };
void opcode_not_zero(byte_opcode op, Vm* vm) { ... };
void opcode_jump(byte_opcode op, Vm* vm) { ... };
void opcode_default(byte_opcode op, Vm* vm) { /* fixme */ };

OpcodeFuncPtr opcode_table[256] = {
    ...
    opcode_add,
    opcode_not_zero,
    opcode_jump,
    opcode_default,
    opcode_default,
    ... // etc.
};

C에서 opcode_table의 중복성을 제거하는 방법을 모르겠습니다. 아마도 그것에 대해 질문해야 할 것입니다. :)


0

가장 명백한 언어 독립적 인 대답은 일련의 'if'를 사용하는 것입니다.

사용중인 언어에 함수 포인터 (C)가 있거나 1 클래스 값 (Lua) 인 함수가있는 경우 함수의 배열 (또는 목록)을 사용하여 "스위치"와 유사한 결과를 얻을 수 있습니다.

더 나은 답변을 원한다면 언어에 더 구체적이어야합니다.


0

스위치 문은 종종 좋은 OO 디자인으로 대체 될 수 있습니다.

예를 들어 Account 클래스가 있고 switch 문을 사용하여 계정 유형에 따라 다른 계산을 수행합니다.

다른 유형의 계정을 나타내며 모두 계정 인터페이스를 구현하는 여러 계정 클래스로 대체해야한다고 제안합니다.

그러면 모든 유형의 계정을 동일하게 취급 할 수 있고 다형성 덕분에 계정 유형에 대한 적절한 계산이 실행되므로 스위치가 불필요 해집니다.


0

교체하려는 이유에 따라 다릅니다!

많은 통역사는 opcode 실행을 위해 switch 문 대신 'computed gotos'를 사용합니다.

C / C ++ 스위치에서 놓친 것은 Pascal 'in'과 range입니다. 또한 문자열을 켤 수 있기를 바랍니다. 그러나 이것들은 컴파일러가 먹기에는 사소한 것이지만 구조와 반복자 및 사물을 사용하면 어려운 일입니다. 따라서 C의 switch () 만 더 유연하다면 스위치로 바꿀 수있는 많은 것들이 있습니다!


0

스위치는 Open Close Principal을 위반하므로 좋은 방법이 아닙니다. 이것이 내가하는 방법입니다.

public class Animal
{
       public abstract void Speak();
}


public class Dog : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Hao Hao");
   }
}

public class Cat : Animal
{
   public virtual void Speak()
   {
       Console.WriteLine("Meauuuu");
   }
}

그리고 그것을 사용하는 방법은 다음과 같습니다 (코드 사용) :

foreach (var animal in zoo) 
{
    echo animal.speak();
}

기본적으로 우리가하고있는 일은 부모가 자녀와 함께 무엇을해야할지 결정하는 대신 자녀 클래스에 책임을 위임하는 것입니다.

"Liskov 대체 원칙"을 읽어 보길 원할 수도 있습니다.


0

연관 배열을 사용하는 JavaScript에서
:

function getItemPricing(customer, item) {
    switch (customer.type) {
        // VIPs are awesome. Give them 50% off.
        case 'VIP':
            return item.price * item.quantity * 0.50;

            // Preferred customers are no VIPs, but they still get 25% off.
        case 'Preferred':
            return item.price * item.quantity * 0.75;

            // No discount for other customers.
        case 'Regular':
        case
        default:
            return item.price * item.quantity;
    }
}

이된다 :

function getItemPricing(customer, item) {
var pricing = {
    'VIP': function(item) {
        return item.price * item.quantity * 0.50;
    },
    'Preferred': function(item) {
        if (item.price <= 100.0)
            return item.price * item.quantity * 0.75;

        // Else
        return item.price * item.quantity;
    },
    'Regular': function(item) {
        return item.price * item.quantity;
    }
};

    if (pricing[customer.type])
        return pricing[customer.type](item);
    else
        return pricing.Regular(item);
}

예의


-12

if / else에 대한 또 다른 투표. 나는 그것을 사용하지 않는 사람들이 있기 때문에 대 소문이나 스위치 진술에 열광하지 않습니다. case 또는 switch를 사용하면 코드를 쉽게 읽을 수 없습니다. 어려울 수도 있지만 명령을 사용할 필요가없는 사용자에게는 읽기 어려울 수도 있습니다.

객체 팩토리도 마찬가지입니다.

If / else 블록은 누구나 얻을 수있는 간단한 구성입니다. 문제가 발생하지 않도록하기 위해 할 수있는 일이 몇 가지 있습니다.

첫째-if 문을 두 번 이상 시도하지 마십시오. 들여 쓰기를 발견하면 잘못하고 있습니다.

 if a = 1 then 
     do something else 
     if a = 2 then 
         do something else
     else 
         if a = 3 then 
             do the last thing
         endif
     endif 
  endif

정말 나쁘다-대신 이것을하십시오.

if a = 1 then 
   do something
endif 
if a = 2 then 
   do something else
endif 
if a = 3 then 
   do something more
endif 

최적화가 저주되었습니다. 코드 속도와 크게 다르지 않습니다.

둘째, 특정 코드 블록을 통해 흩어져있는 break 문이 충분하기 만하면 If 블록에서 벗어나는 것을 피하지 않습니다.

procedure processA(a:int)
    if a = 1 then 
       do something
       procedure_return
    endif 
    if a = 2 then 
       do something else
       procedure_return
    endif 
    if a = 3 then 
       do something more
       procedure_return
    endif 
end_procedure

편집 : On Switch와 왜 어려운지 생각합니다.

다음은 switch 문의 예입니다 ...

private void doLog(LogLevel logLevel, String msg) {
   String prefix;
   switch (logLevel) {
     case INFO:
       prefix = "INFO";
       break;
     case WARN:
       prefix = "WARN";
       break;
     case ERROR:
       prefix = "ERROR";
       break;
     default:
       throw new RuntimeException("Oops, forgot to add stuff on new enum constant");
   }
   System.out.println(String.format("%s: %s", prefix, msg));
 }

나에게 여기서 문제는 C와 같은 언어로 적용되는 일반적인 제어 구조가 완전히 손상되었다는 것입니다. 제어 구조 내에 둘 이상의 코드 줄을 배치하려면 중괄호 또는 begin / end 문을 사용하는 일반적인 규칙이 있습니다.

예 :

for i from 1 to 1000 {statement1; statement2}
if something=false then {statement1; statement2}
while isOKtoLoop {statement1; statement2}

나를 위해 (그리고 내가 틀렸다면 나를 교정 할 수있다) Case 문은이 규칙을 창 밖으로 던져 버린다. 조건부로 실행 된 코드 블록은 시작 / 종료 구조 내에 배치되지 않습니다. 이 때문에 Case는 사용하지 않을 정도로 개념적으로 다르다고 생각합니다.

질문에 대한 답변을 바랍니다.


와우-분명히 논쟁의 여지가 있습니다. 내가 뭘 잘못했는지 알고 싶어요.
seanyboy

어, 너무 복잡한 것으로 전환? 잘 모르겠습니다 ... 사용할 수있는 언어 기능이 많지 않은 것 같습니다. :) 또한 중앙 예제에서 (a == 1 || a == 2 || a == 3) 무언가를 수행하는 것이 더 똑똑하지 않습니까?
Lars Westergren

또한 마지막 예제에서 "break"는 대부분의 언어에서 가장 가까운 블록 (보통 루프)을 벗어나는 작업을 수행하지 않으므로 다음 줄 (endif)에서 발생합니다. 당신은 휴식 ( "가드 문"을 제외하고) 많은 수익률도 눈살을 찌푸리게된다 "반환"인 언어를 사용하는 경우
라스 웨스터 그렌

4
"최적화가 저주되었습니다. 코드 속도에 큰 차이는 없습니다." 내 코드는 모바일 플랫폼에서 실행됩니다. 최적화가 중요합니다. 또한 스위치를 올바르게 사용하면 스위치가 코드를 매우 깨끗하게 보일 수 있습니다 (if..elseif..elseif..elseif ...와 비교). 본 적이 없습니까? 그들을 배우십시오.
Swati

스위치는 전혀 복잡하지는 않지만 코드에서 사용되는 구조의 수를 최소화하여 이해의 마찰을 줄이기 위해 항상 노력했습니다.
seanyboy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.