2013-07-16 7 views
4

왜 나는 다운 캐스팅이 필요한지 알아 내려고하고 있습니다. 콜라주에서 내 노트를 다시 읽었으며 아래 예제를 발견했습니다.우리는 왜 왜 다운 캐스팅이 필요한가요?

class Student {...} 

class Graduate exteds Student { 
    getResearchTopic(){...} // this method only exists in Graduate class. 
} 

우리는 학생 클래스에 대한 심판을 가지고 getResearchTopic 방법에 액세스 할;

Student s1 = new Graduate(); 
if(s1 instanceof Graduate){ 
    ((Graduate)s1).getResearchTopic(); 
} 

다운 캐스팅을위한 훌륭한 예 하? 제 질문은 왜 s1을 대학원으로 선포하지 않는 것입니까? 실제 수업의 인스턴스를 사용하는 대신 다운 캐스트해야하는 실제 사례가 있습니까?

+2

내가 사용이 경우 downcasting 보이는 것을 말할 것 읽고있는 개체의 어떤 종류 확인할 수있는 방법 - readObject() 항상 평범한 오래된 Object를 반환하기 때문에, 실제 타입으로 obj 캐스팅 응용 프로그램의 디자인 문제처럼. 다운 캐스팅을 사용해야하는 곳 중 하나는 '같음'메소드를 오버라이드 할 때입니다 (가능한 dup 질문에 표시됨). –

+0

나는 어쨌든 대답 = \ 너무 오래 걸렸다. –

답변

3

글쎄, s1이라는 참조를 Graduate으로 선언했을 수 있습니다. super type이라는 참조를 선언하면 얻을 수있는 가장 큰 이점은 다형성입니다.

하위 유형 객체를 가리키는 수퍼 유형 참조를 사용하면 동일한 참조를 여러 하위 클래스 객체에 바인딩 할 수 있습니다. 실제로 호출되는 실제 메소드는 어떤 객체가 가리키고 있는지에 따라 런타임에 결정됩니다. 그러나 이것의 주된 조건은 이며 그 메소드는 서브 클래스에도 정의되어야합니다. 그렇지 않으면 컴파일러은 메소드 선언을 찾지 못합니다.

여기에서는 수퍼 클래스에서 메서드를 정의하지 않았기 때문에 downcast이되었습니다. 컴파일러는 Student 클래스에서 해당 메서드의 정의를 볼 수 없습니다. 실제 개체 인 s1이 무엇을 가리키고 있는지 전혀 알 수 없습니다. 컴파일러는 참조 유형을 검사하여 메토 드 선언을 찾습니다.

일반적으로 코드의 하위 클래스로 다운 캐스팅 될 때마다 거의 항상 잘못된 기호가 나타납니다 (예외는 있지만). 그리고 수업을 수정해야합니다. 예를 들어

:


이의 대신 서브 클래스 참조의 수퍼 클래스 참조를 사용하여 얻을 어떤 이점 보자

class Phd extends Student { 
    getResearchTopic(){...} 
} 

과 : 당신은 같은 Student의 또 다른 서브 클래스가 있다고 가정 Student 클래스에 정의 (기본값)를 제공합니다.

class Student { 
    getResearchTopic(){...} 
} 

지금, 당신은 둘 다 Student 참조로 지적되고하는 다음과 같은 두 개체를 만들 :

Student student = new Phd(); 
student.getResearchTopic(); // Calls Phd class method 

student = new Graduate(); 
student.getResearchTopic(); // Calls Graduate class method 

그래서, 단지 하나의 참고로, 당신은 하위 클래스에 고유 한 접근 방법에 도착.


단일 정적 방법은 어떤 조건에 따라 서로 다른 서브 클래스의 객체를 반환 factory method 패턴에서 볼 수있는이 기능을 하나의 주요 구현 : 그래서

public static Student getInstance(String type) { 
    if (type.equals("graduate")) 
     return new Graduate(); 
    else if (type.equals("phd")) 
     return new Phd(); 
} 

를 볼 수 있습니다 동일한 메소드는 다른 하위 클래스의 객체를 반환합니다.

그냥 있기 때문에 하나 개의 개념으로 할 수있는 위의 거즈의 모든

:

슈퍼 클래스 참조가 하위 클래스의 객체를 참조 할 수 있지만 그 반대.

+6

* s1을 대학원생으로 선언하는 것이 어떨까요? 이것은 OP의 주요 관심사입니다. 아마도이 부분을 해결하기위한 답을 넓혀야 할 것입니다. –

+0

@ LuiggiMendoza John. 죄송합니다. 이전에 질문을 잘못 읽었습니다. 지금 편집했습니다. –

+0

실제로 다운 캐스팅을 사용하면 다형성 *이 저하됩니다. –

0

다형성을 사용하려는 경우 Student 개체로 작업 한 다음 Graduate 개체에 해당하는 메서드를 사용하려면 "다운 캐스트"하는 것이 좋습니다. 일반적으로

, 당신은 Student 객체와 함께 작동하는 방법이있는 경우, 그 방법은 정말 전달되는 Student 객체의 특정 유형을 컴파일 타임에 알 수 없습니다. 따라서, 실행시, 방법 확인해야 이에 따라 특정 유형 및 프로세스에 대해

6

Student을 매개 변수로 사용하는 메서드가 있다고합시다. 그것이하는 일의 대부분은 모든 학생들에게 일반적입니다. 그러나 그것이 Graduate 인 경우에는 다른 것도있을 수 있습니다. 이 경우 Student이 실제로 Graduate인지 확인하고 해당 인스턴스에서 특수 논리를 수행해야합니다. 이 같은

아마 뭔가 : 그런 종류의 일을하는 것은 일반적으로 가난한 프로그래밍 연습이지만, 때로는 의미가 있음을

class StudentDAO { 
    public void SaveStudent(Student s) { 
     // Do something to save the student data to a database. 

     if (s instanceof Graduate) { 
      // Save their research topic too. 
     } 
    } 
} 

참고.

0

다운 캐스팅은 일반적인 방법을 만들려고 할 때 도움이됩니다. 예를 들어 XML StringObject으로 구문 분석하는 코드가 자주 표시됩니다. 그러면 Object은 사용자가 (코더로) 알 수있는 특정 Object으로 다운 캐스트 될 수 있습니다.

private static XStream xstream = new XStream(new DomDriver()); 
static { 
    xstream.processAnnotations(MyFirstClass.class); 
    xstream.processAnnotations(MySecondClass.class); 
    // ... 
} 

public static Object fromXML(String xml) { 
    return xstream.fromXML(xml); 
} 

이렇게하면 모든 경우에 내가 원하는 것을 수행하는 매우 일반적인 방법을 만들 수 있습니다. 그런 다음 전화를 걸면 Object을 내가 알고있는 것으로 다운 캐스팅 할 수 있습니다. 모든 객체 유형에 대해 별도의 구문 분석 메소드를 작성하지 않아도되고 코드의 가독성이 향상됩니다. 기본 자바 디시리얼라이저를 사용하여 객체를 직렬화 할 때

MyFirstClass parsedObject = (MyFirstClass) MyXMLTransformer.fromXML(xml); 
+1

당신의 경우에이 메소드를 Xml (String xml, Class clazz)에서 private T로 재정의하고 실제적인 일반적인 방법으로 만들면 다운 캐스팅 문제를 피할 수 있습니다. –

+0

@LuiggiMendoza 나는 그것이 사실이라고 생각한다. :) 좋은 지적. – asteri

0

, 당신은이 코드를 사용 (그리고, 예를 들면 잭슨 JSON 디시리얼라이저 다른 디시리얼라이저를 사용할 때 당신은 유사한 코드를 사용)

ObjectInputStream ois = new ObjectInputStream(in); 
Object obj = ois.readObject(); 

그런 다음에 필요 정적