2010-02-14 5 views
5

저는 Element라는 기본 클래스가 있습니다. Label 및 Image와 같은 일부 다른 클래스는이 클래스를 확장합니다.오버로드 된 메서드 우선 순위

내가 지금 파견 클래스는 다음과 같은 방법을 가지고있다 : 나는 (요소를 확장) 라벨의 인스턴스가 이제 경우

public class Dispatcher { 
    public static AbstractPropertyEditor<Label> createEditor(Label e) { 
    ... 
    } 

    public static AbstractPropertyEditor<Element> createEditor(Element e) { 
    ... 
    } 
} 

을 내가 createEditor()에 전달하려는 이유는 가장 일반적인 방법입니다 (두 번째 것)은? 보통 특정 방법 (createEditor(Label e))이라고 불리는 것이 정상이 아니겠습니까? 내가

을 사용하고

나는 절대적으로 .. 순서가) 요소를 구현하지만,이 파견 클래스에서 자신의 구체적인 방법이없는이 "잡아"모든 클래스의 요소-PARAM와 방법이 필요합니다 Java 6,이 "수정"방법?

편집 : 좋아, 제네릭에 대해서는 전혀 인정하지 않아도됩니다. 그러나 그것이 처음으로 만난 곳입니다.

감사와 관련

+0

인스턴스가'Element'가 아닌'Label' 유형의 변수에 할당 되었습니까? –

+0

('T 요소가'Label' 일 때'T 요소를 확장하지 않습니다?) –

답변

6

은 왜 당신을 수행

  • 는 기본 createEditor() 구현에게 createEditor()를 오버라이드 (override) Label
  • 메이크업을 제공 Element 추상 클래스를 만든다.

따라서 정적 유틸리티가 필요하지 않으며 목표를 달성 할 수 있습니다.

당신은 다음 인터페이스로 Element을해야하는 경우 :

  • DefaultEditorFactoryListEditorFactory
  • 을 제공 EditorFactory 인터페이스를 정의 Element

  • 의 방법으로 createEditor()를 정의에서 해당 공장을 사용 Element의 구현 자 :

    콘크리트 EditorFactory 초기화 중 또는 실행 종속 주입 어떤 종류의를 통해 하나 인스턴스화
    public Editor createEditor() { 
        editorFactory.createEditor(this); 
    } 
    

.


귀하의 구체적인 질문에 따라 - 당신이 거기에 컴파일 된 유형에 따라 다릅니다. 당신이 createEditor(obj)를 호출하면 그것에서 Element obj = .. 또는 Label obj = ..

+0

hmmmm ... Element 및 하위 클래스에서 createEditor를 구현하는 아이디어가 ... 첫 번째 인스턴스에서 나쁜 생각처럼 들리지 않는다고 생각해보십시오. 내 상황에서는 그런 식으로 사용할 수 있을지도 모릅니다. 그러나 분리를 위해 여전히 정적 유틸리티 클래스를 분리하고 싶다면 어떻게해야할까요? Java가 내 케이스에서 전화 할 방법을 어떻게 결정합니까? 항상 가장 일반적인 것을 호출합니까? 가장 구체적인 방법이라고 할 수있는 방법이 있습니까? – Atmocreations

+0

내 대답이 업데이트되었습니다. 정확한 행동을 위해 다른 사람들의 답을 볼 수 있습니다. – Bozho

+0

본, thx. 음 ... 문제는 메서드를 호출하기 전에 Label에 그 것을 던지기 싫어한다는 것입니다. 그렇지 않으면 createLabelEditor (Label l), createImageEditor (Image i) 등과 같은 메소드를 직접 작성할 수 있습니다. 이는 Element를 매개 변수로 갖는 메소드를 사용하지 않을 것입니다. – Atmocreations

0

당신은 아마 일을 보낸 사람 :

Element element = new Label(); 

은 컴파일러에 의해 결정된다.

+0

간접적으로 잘 보입니다 (상황에 따라 다른 메서드 호출). 실제로 어떤 메소드가 호출되는지를 결정하기 위해 var 요소의 선언 된 타입에 의존 하는가? "실제"유형 (레이블)의 메소드가 호출되지 않습니까?그리고 그렇지 않다면, 이것에 대한 이유는 무엇입니까? – Atmocreations

2

이것은 제네릭과는 거의 관계가 없으며 메서드 오버로딩과 관련이 있습니다. Java에서 호출되는 메서드 서명은 런타임이 아닌 컴파일 타임에 결정되므로 런타임에 확인하고 캐스트해야합니다.

그래서 대체 :이

Element label = getLabel(); 
AbstractPropertyEditor<?> editor = createEditor(label); 

:

Element label = getLabel(); 
AbtractPropertyEditor<?> editor; 
if(label instanceof Label) { 
     editor = createEditor((Label) label); 
} else { 
     editor = createEditor(label); 
} 

이가 createEditor를을하는 것입니다 해결하기 위해 다른 (더 표준/더 나은) 방법 (요소) 메소드는 유형을 확인하고 서브 타입에 대한 정확한 오버로드 된 메소드를 형변환 (cast)하여 호출하십시오. 그러나 선언 된 메소드에서 수행하는 경우 반환 매개 변수에 문제가 있습니다.

+0

좋은 반응을 보내 주셔서 감사합니다. 그러나 가능하면'instanceof'를 피하고 싶습니다. 그러므로, 이것은 나에게 선택 사항이 아닙니다. – Atmocreations

+0

@Atmocreations, 다음 매개 변수로 슈퍼 및 하위 형식으로 메서드 오버로드를 사용하지 않는 것이 좋습니다. 그러한 패턴은 필연적으로 인스턴스와 캐스팅으로 이어진다. – Yishai

1

여부 따라 달라집니다 Java Language Specification :

메소드가 호출

(§15.12), 실제 인수의 수 (및 명시 적 형식 인수) 그리고 컴파일시에 이 컴파일시에 이고, 컴파일시에, 으로 이 호출되고, 호출 될 메소드 (§15.12.2)의 서명을 결정하십시오. 호출 될 방법은 인스턴스 방법이면 호출 의 실제 방법은 동적 룩업 방법을 사용하여 실행 시간 에서 을 결정한다 (§15.12.4).

+0

thx. 그러나 이것은 절대적으로 정확하지만, 현재의 문제에 도움이되지도 않으며, 결국 Java가 어떤 메소드가 실제로 호출되는지 결정하는 방법을 설명하지도 않습니다. – Atmocreations

+0

@Atmocreations : 나는 다르 겠지만, 인스턴스가 아닌 메서드의 경우에는 호출 된 메서드가 컴파일 타임에 인수의 형식에 해당하는 메서드가됩니다. 귀하의 경우에는 그것이 호출되는 요소 하나이므로, 그것은 당신이 요소를 컴파일 타임에 호출하는 것을 의미합니다. – JRL

+0

글쎄 ... 실례합니다. 나는 내가 아직 그렇게 보지 못했다는 것을 인정해야한다. – Atmocreations

0

다음은 오버로드 된 메서드의 예입니다. 런타임시 실제 객체가 Label이 아니고 Element가 아닌 경우에도 에서 호출 할 오버로드 된 메서드 (즉, 메서드의 시그니처)를 선택하는 것은 런타임에 동적으로 결정되지 않습니다. 참조 유형 (객체 유형이 아님)은 호출 된 오버로드 된 메소드를 판별합니다.

public class Car {  
} 

public class Toyota extends Car {  
} 

public class MyCar { 

    public void run(Car c) { 
     System.out.println("Run any Car"); 
    } 

    public void run(Toyota t) { 
     System.out.println("Run Toyota Car"); 
    } 

    public static void main(String[] args) { 
     MyCar myCar = new MyCar(); 

     Car c1 = new Car(); 
     myCar.run(c1); // Output: Run any Car 

     Toyota c2 = new Toyota(); 
     myCar.run(c2); // Output: Run Toyota Car 

     Car c3 = new Toyota(); 
     myCar.run(c3); // Output: Run any Car  
    } 
} 

따라서, 귀하의 경우 다른 주에

Element obj1 = new Label(); 
Dispatcher.createEditor(obj); // Method with Element argument is called 
           // as you are passing Element 

Label obj2 = new Label(); 
Dispatcher.createEditor(obj); // Method with Label argument is called 
           // as you are passing Label 

에서 재정의 된 메서드 호출은 런타임에 발생하며, 즉 (개체 유형의 유형을 따라 힙의 실제 인스턴스)