2011-07-06 3 views
6

org.junit.Assert.assertEquals 메서드를 정적으로 가져 오는 Junit4 테스트 사례가 있습니다. 내가 등호를 구현하지 않는 일부 복잡한 내부 클래스를 주장하기위한 유틸리티 메소드를 만든이 클래스에서 클래스에 가져온 클래스와 같은 이름의 메서드가있는 경우 가져 오기 static이 작동하지 않습니다.

import static org.junit.Assert.assertEquals; 

(그리고 또한 힘든 시간을 구현있다).

private void assertEquals(MyObj o1, MyObj o2) 
{ 
    assertEquals(o1.getSomething(), o2.getSomething()); 
    assertEquals(o1.getSomethingElse(), o2.getSomethingElse()); 
    ... 
} 

나는 내가 가져있어 assertEquals 방법 (들) "과부하"하고있는 것처럼 코드가 작동 할 것으로 예상하지만, 정적으로 수입 된 방법을 숨기고 내 개인 비 정적 방법처럼 보인다 . 나는 또한 내 방법을 publicstatic (모든 순열)이 되려고했지만 성공하지 못했습니다. 이름을 변경해야했습니다.

이 방식으로 작동하는 이유는 무엇입니까? 설명서에서이 동작에 대한 참조를 찾을 수 없습니다.

+1

내부 메소드의 서명 (또는 이름)을 변경하지 못하게하는 것은 무엇입니까? – spot35

+1

@DomSelvon, 서명을 변경해도 도움이되지 않습니다. 메서드 이름 - 아무 것도 나를 막지 않습니다 - 질문은 이제 지식을위한 것입니다 (이미 이름이 변경되었습니다) – RonK

답변

3

관찰 한 내용은 Shadowing입니다. java에서 두 개의 유형이 동일한 간단한 이름을 가질 때, 그 중 하나는 다른 하나를 어둡게합니다. 그림자가있는 유형은 단순한 이름으로 사용할 수 없습니다.

가장 일반적인 섀도 잉 유형은 필드를 숨기는 매개 변수입니다. 일반적으로 setMyInt(int myInt) {this.myInt = myInt; }

처럼 보이도록 세터 코드가 발생할 이제이 relevant documentation을 읽어 보자

정적 가져 오기 주문형 선언은 결코 그림자가되는 다른 선언을 발생하지 않습니다.

이는 주문형 정적 가져 오기가 항상 마지막임을 나타냅니다. 따라서 주문형 가져 오기 선언과 동일한 간단한 이름을 가진 모든 유형은 항상 정적 가져 오기를 섀도 잉 (숨김)합니다.

+0

그게 사실 인 것 같아요. 비록 제가 고백해야하지만, 당신의 설명과 스펙을 모두 읽은 후에도, 저는 특정 서명을 가진 하나의 방법이 다른 하나를 왜 왜 그림자인지 이해하지 못합니다. – RonK

+0

당신은 어떤 행동을 설명 할 수 있습니까? 이 경우에 기대하니? 두 메소드 모두 동일한 간단한 이름을 가지고 있기 때문에, 컴파일러가 너무 호출하려고 시도한 메소드 (개인용 및 가져온 정적 메소드)를 마술처럼 추측 할 방법이 없기 때문에 섀도 잉 규칙을 사용하여 선택해야합니다. – Dorus

+0

아니면 다른 방법보다 한 가지 방법을 선호하는 이유를 아직 알지 못했습니까? 그것은 신중하게 규칙을 읽고 스펙에 적용하는 것입니다. 전반적으로 당신은 로컬 물건을 선호하고 클래스를 선택한 다음 상속 된 다음 가져온 다음 필요에 따라 가져올 수 있다고 말할 수 있습니다. – Dorus

1

오버로드 및 덮어 쓰기는 상속 트리에서 작동합니다. 그러나 정적 가져 오기는 상속을 구축하지 않습니다.

자신의 assertEquals 메소드에서 junit의 assertEquals를 사용하려면 className으로 정규화해야합니다. 예 : Assert.assertEquals.

org.junit.Assert의 정적이 아닌 가져 오기를 사용하십시오.

+0

이것은 사용자 정의 메서드의 이름을 변경하지 않고 가장 좋은 대답 인 것 같습니다. – Joseph

0

method hiding으로 넘어갔습니다. 로컬 메서드가 있으면 다른 클래스 (대개 수퍼 클래스)에서 "숨 깁니다".

정적으로 가져 오는 방법은 구문 상 가능하지만 여하튼 "잘못"하다고 항상 느꼈습니다.

스타일로 클래스를 가져오고 내 코드에 TheirClass.method()을 사용하는 것을 선호합니다. 이렇게하면 메서드가 로컬 메서드가 아니며 좋은 코드의 특징 중 하나가 선명도임을 분명하게 알 수 있습니다.

나는 import org.junit.Assert을 추천하며 Assert.assertEquals(...)을 사용합니다.

+0

이 스타일을 사용하면 메서드의 출처를 명확하게 알 수 있습니다. 그러나 명확한만큼 중요한 질문은 "그것은 무엇을 하는가?"입니다. 그 점을 고려하여 당신은 근사하게 아무것도 밝히지 않고 문자 수를 두 배로 늘 렸습니다. –

+0

Dorus와 마찬가지로, 이것은 _hadow_가 아니라 [_shadowing_] (http://docs.oracle.com/javase/specs/jls/se7/html/jls-6.html#jls-6.4.1)입니다. Assert.assertEquals 메소드는 상속되지 않습니다. –

0

이것은 의미가 있습니다. javac가 원하는 것을 수행한다고 가정하면, 오늘은 assertEquals(MyObj, MyObj) 메소드를 선택합니다. 내일 org.junit.AssertassertEquals(MyObj, MyObj) 메서드가 추가되면 어떻게 될까요?부름 assertEquals(mo1,mo2)의 의미는 당신이 모르게 극적으로 변했습니다.

문제의 이름은 assertEquals입니다. Javac은 이것이 방법의 이름 (org.junit.Assert)임을 결정해야합니다. 그 후에 만 ​​메소드 오버로딩을 수행 할 수 있습니다. 의 메소드를 모두 assertEquals으로 검사하고 가장 적합한 메소드를 선택하십시오.

자바는 여러 클래스의 메소드 오버로드를 처리 할 수 ​​있지만 첫 번째 단락에서 볼 수 있듯이 개발자가 호출하는 메소드의 클래스에 큰 불확실성이 있습니다. 이러한 클래스는 서로 관련이 없으므로 메서드 의미가 크게 다를 수 있습니다.

컴파일 타임에 메서드가 속한 클래스를 개발하는 데 의심의 여지가없는 경우에도 클래스가 내일 메서드를 오버로드하여 호출 된 대상 메서드를 변경하는 것이 여전히 가능할 수 있습니다. 그러나 동일한 클래스에서 수행되므로 책임을 맡을 수 있습니다. 예를 들어 org.junit.Assert이 새로운 assertEquals(MyObj, MyObj) 메서드를 추가하기로 결정한 경우 이전 호출 인 assertEquals(Object,Object)이 새 메서드로 리 라우팅되고 호출 사이트를 손상시킬 의미 변경이 없는지 확인해야합니다.