2013-07-11 4 views
4

저는 왜 Graphics 인스턴스를 Graphics2D 인스턴스로 다운 캐스팅 할 수 있는지 알아 내려고하고 있습니다.그래픽 인스턴스 다운 캐스트 - 왜 허용됩니까?

대상 유형을 상속하지 않는 참조 유형 을 다운 캐스팅하는 것은 일반적으로 반대되는 규칙입니다. 그래픽 중심의 수업에서

계층 구조는 같다 다음

  1. 그래픽 슈퍼
  2. 의 Graphics2D입니다 슈퍼 그래픽의 서브 클래스는

스윙에 뭔가를 그리기 당신 paint() 메소드를 오버라이드합니다. 2D 드로잉이 필요한 경우 paint() 메서드에서 자동으로 제공된 Graphics 인스턴스를 Graphics2D 인스턴스로 다운 캐스팅합니다.

public void paint(Graphics g) 
{ 
    super.paint(g); 

    Graphics2D g2d = (Graphics2D)g; 
} 

하지만 역순입니까? Graphics 인스턴스가 이 아니고이 graphics2D 인스턴스를 상속합니다. 이 클래스 계층을 볼 때 Graphics 인스턴스를 상속 한 것은 Graphics2D 인스턴스입니다!

왜 허용됩니까?

+0

'Graphics' 인스턴스가'Graphics2D'가 아닌 경우 이것은 단지 예외를 던집니다. –

+1

일반적으로 프로그래머가 형식 시스템을 우회해야하기 때문에 일반적으로 다운 캐스팅이 허용됩니다. 이는 유형 시스템의 결함이나 API 디자인의 결함 때문일 수 있습니다. '페인트 '의 경우 스윙 API의 결함이라고하지만 그 점은 제 의견입니다. –

답변

2

Graphics에서 상속받은 클래스입니다. "인간"이 "biped"클래스와 같은 방식으로 모든 인간이 바이 패스이지만 모든 바이 페드가 인간이라는 것은 사실이 아닙니다.

java.awt.Graphics은 Java의 가장 초기 날짜이며 매우 정교하지 않았습니다. Waphen Swing과 Java2D가 생성되었으므로 Graphics2DGraphics의 하위 클래스로 만들어져 이전 코드가 작동하도록합니다 - 이전 버전과의 호환성은 Sun의 종교 였지만 나쁜 것은 아닙니다.

JComponent 및 기타 Swing 클래스는 이전 API를 사용하는 java.awt.Component에서 상속받습니다. 수퍼 클래스 이외의 다른 변경없이 사람들이 AWT에서 Swing으로 쉽게 마이그레이션 할 수 있도록 Swing은 Graphics2D이 아닌 Graphics이라는 서명을 유지했습니다.

스윙에서 paint(Graphics)으로 전달 된 그래픽은 항상 Graphics2D이므로, 그렇지 않은 경우를 처리하기 위해 대체 코드 경로가 필요하지 않음이 잘 설명되어 있습니다.

1

그래픽은 Graphics2D의 수퍼 클래스입니다. 왜이 캐스팅이 필요한지에 대해서는 확실하지 않습니다. 그것도 저를 귀찮게합니다.

편집 :

Check this out:

의 Graphics2D는 JDK 1.1 이후에 도입되었다. 레거시 프로그램과의 하위 호환성을 유지하려면 GraphicsGraphics2D으로 다운 캐스트해야한다고 생각합니다.

더 고급 기능에 액세스하려면 Graphics2D로 캐스팅하십시오. 이것은 베스트 프랙티스를 깨뜨렸지 만 이전 버전과의 호환성을 유지하는 데 가치가 있다고 여겨졌습니다.

+2

당신은 downcast 때문에'Graphics'에서 사용할 수없는 Graphics2D의 메서드를 사용하려고합니다. – nachokk

+1

Duh lol. 특정 인스턴스로 다운 캐스팅이 일반적으로 바람직하지 않기 때문에 자바 신이이 접근법을 사용한 이유에 대해 궁금합니다. –

+0

스윙은 일반적으로 바람직하지 않습니다. JTextField가있을 때 적어도 10 개 이상의 슈퍼 타입을 가지고 있다고 생각하십시오. 그들은 상속으로 많은 것을 할 수 있습니다. 그래서이 일이 일어나고 또한'super.paint()'를 호출하는 것이 좋지 않습니다. 그 또는 다른 것을위한 템플릿 메소드를 만듭니다. – nachokk

3

g이 실제로 런타임시 Graphics2D의 인스턴스가 될 것이라는 것을 알고 있다면 허용됩니다. 그렇지 않은 경우 런타임에 ClassCastException이 표시됩니다. 당신이 Graphics에 대한 documentation을 선택하면

, 당신은 Graphics, Graphics2DDebugGraphics의 두 기존의 서브 클래스가 있다는 것을주의 할 것이다. 따라서 Graphics 하위 클래스의 사용자 정의 구현을 제외하면 Graphics2D 인스턴스를 처리하는 것이 확실 할 수 있습니다.

+0

이것은 내가 생각하지 않는 그가 요구하는 것이 아닙니다. 그는 왜 우리가 특정한 경우로 추방 하는가를 묻고 있습니다. 왜 이런 것들이 내가 생각한 방식으로 설계 되었는가? –

+0

@ 윌리암 모리슨 나는 다운 캐스팅에 대해 혼란 스럽다고 생각한다.이 대답은 정확하다. +1 – nachokk

+0

@nachokk 나는 왜이 다운 캐스트가 내 대답에 necssary인지 설명한다. 아니면 적어도 내가 왜 그렇게 생각하는지. 나는 누군가를 위해 나를 정정하기를 원합니다. 자바 2d 그래픽을 배웠던 이래로 이것은 귀찮았습니다. –

1

paint 메소드에게 건네진 오브젝트는 Graphics2D 타입입니다. 프로그래머로서 당신은 메소드 서명에서 명시 적이지는 않지만 이것을 알고 있습니다 (일반적으로 사실 일 필요는 없기 때문에). 따라서 객체를 캐스팅 할 수 있습니다.

+0

Graphics 객체는 Graphics2D 객체가 아닙니다. 나는 이걸 본 적이 없지만 호기심이 많습니다. –

+0

@ 윌리암 모리슨 나는 같은 것을 궁금해하고 있었다. 나는 이전 버전과의 호환성을 위해 이렇게 생각합니다. –

+0

나는 잠시 동안 그렇게 생각했지만, Graphics2D는 영원히 주변에 없었습니까? –

1

혼란스러워합니다. Graphics은 Graphics2D의 수퍼 클래스입니다. 당신은 다운 캐스트 할 수 있지만 다운 캐스팅은 실행 시간 예외 인 ClassCastException을 피하기 위해 instanceof을 사용하는 것이 좋습니다.

또한 paintComponent 대신에 paint을 무시하지 않아도됩니다.

1

때때로 실제 유형을 알 수없는 코드에서 데이터를 가져 오기 때문에 다운 캐스팅이 유용합니다. entity가이 확실히 더 특정 유형의 경우에도 Object로 입력되는 것을 the Hibernate Interceptor interface

public void onDelete(Object entity, 
        Serializable id, 
        Object[] state, 
        String[] propertyNames, 
        Type[] types) { 
    // do nothing 
} 

주에서이 예를 생각해 보자. Hibernate는 아마도이 지속되는 엔티티의 유형에 컴파일 시간 기준을 가질 수 없습니다,하지만 여전히 유용한 방법이 될 수 있습니다 :이 예에서

if (entity instanceof Auditable) { 
    Auditable data = (Auditable)entity; // downcast 
    logger.warn("{current user} is deleting " data.GetDescriptionForAudit()); 
} 

, 캐스트 피할 수 없다 - 하이버 네이트 API는 할 수 없습니다 향상시킬 수있는 가장 좋은 유형은 Object입니다.

스윙의 paint 메서드의 경우 메서드 서명에 Graphics2D이 사용 된 것 같습니다. 그렇지 않으면 필요한 메서드가 Graphics 클래스에 정의되어 있어야합니다. 아마도 스윙의 디자이너는 "정말 필요하지 않으면 Graphics2D 방법에 의존하지 말라고 말하려고합니다."

때로는 프로그래머가 그것을 할 수 있기 때문에

Downcasting이 허용되는 질문에 대답합니다. Hibernate 예제에서, API는 입력 될 수있을뿐만 아니라 입력된다. 스윙 예에서 API에 결함이 있다고 주장 할 수 있습니다. 그러나 어느 경우 든 Java가 다운 캐스팅을 허용하는 것이 유용합니다.

0

실제로 Graphics2D은 그래픽의 하위 클래스입니다. 우리가 그래픽의 인스턴스를 인수로 전달할 때 (Graphics g), 내부적으로 gg = new Graphics2D으로 선언됩니다. Graphics2D은 그래픽의 하위 클래스이므로 따라서 gGraphics 2D의 인스턴스이고 datatype of graphics.Therefore인데 g에서 graphics 2d까지 다운 캐스트 할 수 있습니다.