2009-05-29 2 views
21

내가 가진 if에서 테스트를 수행 할 수있는 가장 좋은 방법은 무엇인가 등 WhereStatement, IfStatement라는 이름의 여러 가지 다른 클래스에서 상속합니다없는 baseclass, Statement, ... 문이 인스턴스가 파생 된 Statement 클래스의 종류를 결정하려면?합니까 자바는이 시험 방법 "클래스의 일종이다"

답변

53
if (obj.getClass().isInstance(Statement.class)) { 
    doStuffWithStatements((Statement) obj)); 
} 

이 기술에 대한 좋은 점은 ("instanceof"키워드와 대조적으로) 테스트 클래스를 객체로 전달할 수 있다는 것입니다. 하지만, 그 외에는 "instanceof"와 동일합니다.

참고 : 나는 의도적 대해 editorializing을 피했다 여부를 입력 인스턴스 검사가 할 수있는 권리 것입니다. 예, 대부분의 경우 다형성을 사용하는 것이 좋습니다. 그러나 그것은 OP가 요구 한 것이 아니며, 나는 그의 질문에 대답하고 있습니다.

+3

더 간단한 instanceof 확인을 사용하지 않는 이유는 무엇입니까? –

+5

instanceof는 goto처럼 악조건이 아닙니다. 언어에 추가 된 이유와 사용되지 않는 이유가 있습니다. –

+10

+1은 "유형 인스턴스 검사가 올바른지 아닌지에 대해 편집하지 않기"입니다. –

64
if(object instanceof WhereStatement) { 
    WhereStatement where = (WhereStatement) object; 
    doSomething(where); 
} 

이와 같은 코드는 일반적으로 기본 클래스에 다형성 메서드가 없음을 나타냅니다. 즉 doSomething()은 하위 클래스에 의해 무시되는 Statement (가능한 경우 추상적)의 메소드 여야합니다.

+0

추가 정보 주셔서 감사합니다! 디자인을 개선 할 수있는 확실한 방법이 있는지 알아보기 위해 살펴볼 것입니다. –

+5

+1 답변에 대해서는, 비록'instanceof'가 많은 유효한 용도를 가지고 있다고 덧붙이더라도 - 항상 디자인 냄새가있는 것은 아닙니다. 예를 들어'doSomething()'만 where 절에만 적용 할 수 있다면이 패턴은 인위적으로 Statement 클래스의'doSomething()'을 논리적으로 적합하게 만드는 것보다 낫다. – mikera

+0

'instanceof'가 유용한 또 다른 예입니다. JavaFX에는 창 (pane)이 있습니다. 자식 노드의 트리를 탐색해야합니다. 'getChildren()'은 노드를 반환합니다. 그러나 노드 중 하나가 창 인 경우 _its_ 하위를 트래버스해야합니다. Node는'getChildren()'메소드를 가지고 있지 않으며, 하나를 추가하는 것이 아닙니다. 그래서 노드를 창으로 캐스팅하고 자식을 트래버스해야하는지 확인하기 위해'node instanceof Pane'을 사용해야합니다. – dwilliss

6

질문에 대한 답은 instanceof입니다.

그러나 코드에서 instanceof가 필요한 경우 디자인에서 문제가 있다는 것을 나타내는 기호입니다. instanceof가 정당화되는 경우도 있지만 예외가됩니다. 대개 하위 클래스가 다르게 동작해야하는 경우 if() 대신 다형성을 사용해야합니다.

+0

내가 추천 한 것은 인터페이스로 프로그래밍하는 것이 좋습니다. – monksy

0

이것은 이 아닙니다. 객체 지향적 인 방식으로 작업을 수행하는 방법입니다. 이전 코드/데이터 이분법의 근본 원인입니다. 이제는 반드시 나쁜 일은 아니지만 (C가 어떤 것인지 알고 있다면), C와 같은 객체 지향 언어가 아닌 객체 지향 언어로 남겨 두어야합니다.

적절한 디자인을 사용하면 이러한 종류의 동작이 필요하지 않습니다. . 대신 구조의 : 다음

obj.doStuff(); 

각기 다른 obj :

if (obj.getClass().isInstance(Statement.class)) { 
    doStuffWithStatements((Statement) obj)); 
} 

(사과가 자신의 코드를 '훔쳐'에 대한 benjismith하는), 당신은 정말, 따라서 자신의 활동을위한 객체 자체가 책임을 제작한다 클래스는 doStuff에 대한 자체 정의를 갖습니다. 그것이 올바른 방법입니다.

+0

하위 클래스 만 doStuff (™ paxdiabio) 할 수 있고 하위 클래스의 수퍼 클래스 인 객체 배열이있는 경우이 방법이 더 좋습니다 (no-op'd를 추가하는 대신 무의미한 (또는 "단지 잘못") 수퍼 클래스 (들)에 doStuff 메소드. – geowar

+0

@geowar, 만약 당신이 모순이 아닌 것들의 콜렉션을 가지고 있다면 콜렉션에 * 있으면 안된다. 또는, 적어도 당신은 할 수있는 방식으로 컬렉션을 반복해서는 안됩니다. 이를 처리 할 수있는 여러 가지 방법이 있지만 클래스 이름이나 유형에 연결하면 변경시 매우 문제가 될 수 있습니다. 상속/OO 세계에서이 경우에 아무 것도하지 않으려는 수퍼 클래스에 대해 null 함수를 사용하는 것은 사실 매우 유효한 솔루션이므로 처리 코드를 훨씬 더 명확하게 만듭니다. – paxdiablo

1

이 시도 :

if (Statement.class.isInstance(obj)) { 
    doStuffWithStatements((Statement) obj)); 
} 

Class.isInstance() 보낸 방법은 매개 변수로 오브젝트 인스턴스 걸린다.