2009-09-12 3 views
4

오늘 이상한 문제가 발생했습니다. UIView의 하위 클래스를 만들고 xcode에서 제공 한 템플릿 코드에 단 하나의 메서드 만 추가했습니다. 오른쪽목표 C에서 서브 클래 싱 및 캐스팅

UIView *floatView = [[FloatView alloc] init]; 
[floatView floatTest:10.0f]; 

은 매우 간단 :

@interface FloatView : UIView { 

} 
- (void)floatTest:(CGFloat)x; 
@end 

- (void)floatTest:(CGFloat)x { 
    NSLog(@"float was %f", x); 
} 

그런 다음 내 AppDelegate에 내가 이런 코드를했다? 무엇이 인쇄해야합니까? 나는 그것이 "10.0000"과 같을 것이라고 생각했지만, 아니, "0.000000"을 출력합니다.

내가 잘못하고 있었는지 알아 내려고 노력, 시간이 씨름하고 나는 예상 "10.0000"를 인쇄 않았다, 그런 다음에야

FloatView *floatView = [[FloatView alloc] init]; 
[floatView floatTest:10.0f]; 

내 AppDelegate에의 코드를 변경 . 이게 왜 그렇게? FloatView를 UIView의 하위 클래스로 선언했는데, 문제없이 UIView 포인터에 FloatView 객체를 할당해서는 안되나요?

floatView가 UIView에 대한 포인터로 선언되었다고해도 실제로 floatView이고 floatTest 메시지를 처리 ​​할 수 ​​있어야합니까? 나는 여기서 완전히 벗어나고 있니?

+0

코드가 컴파일러 경고를 생성 했습니까? 이유를 파악했다면 문제를 해결했을 것입니다. – bbum

+0

문제가 해결되었을 수도 있지만 그것이 왜 그렇게 행동했는지 이해하지 못했을 것입니다. 귀하의 의견은 실제로 도움이되지 않습니다. 상세한 답변을 해주신 Mehrdad Afshari에게 감사드립니다. –

답변

11

실제로 다형성은 예상대로 작동합니다. 작동하지 않으면 아무 것도 인쇄되지 않습니다 (예제에서 0.0000이 인쇄되고 있음). 컴파일러는 UIView 클래스가 메서드를 선언하지 않으므로 정적으로 메서드 선언을 볼 수 없기 때문에 인스턴스가 실제로 testFloat:10.0f 메시지에 응답하지만 메서드는 ...을 인수로 사용하고 id을 반환한다고 가정합니다.

가변 인수 (...)를 예상하는 메서드에 CGFloat이 전달되면 double으로 승격됩니다. 따라서 수신 방법은 double 인수가 전달되고 float이라고 생각하고 제대로 인쇄되지 않습니다.

당신이 NSLog 라인을 변경하여이 동작을 확인할 수 있습니다

NSLog(@"%f", *(double*)&x); 

컴파일러가 FloatView*보다는 UIView*에 메시지를 보낼 때 방법의 정확한 서명을 찾을 수 있습니다. 그것은 실제로는 CGFloat을 기대하고, 인수를 double로 승격시키지 않음을 알 수 있습니다. 결과적으로 올바르게 작동합니다.

또한 UIView*CGFloat을 사용하는 메서드 선언이 포함되어 있으면 컴파일러에서이 메서드를 적절하게 호출합니다. 요약하면, 이것은 다형성 문제가 아닙니다. 누락 된 메소드 서명 문제입니다.