Objective C의 서브클래싱 및 캐스팅
-
06-07-2019 - |
문제
오늘 이상한 문제를 발견했습니다.UIView의 하위 클래스를 만들고 xcode에서 제공하는 템플릿 코드에 메서드 1개만 추가했습니다.
@interface FloatView : UIView {
}
- (void)floatTest:(CGFloat)x;
@end
- (void)floatTest:(CGFloat)x {
NSLog(@"float was %f", x);
}
그런 다음 내 appDelegate에 다음과 같은 코드가 있습니다.
UIView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
아주 간단하죠?이것은 무엇을 인쇄해야합니까?나는 "10.0000"과 같을 것이라고 생각했지만 아니요, "0.000000"을 인쇄합니다.
나는 내가 뭘 잘못하고 있는지 알아내려고 몇 시간 동안 씨름한 다음 appDelegate의 코드를 다음과 같이 변경했습니다.
FloatView *floatView = [[FloatView alloc] init];
[floatView floatTest:10.0f];
그런 다음에야 예상된 "10.0000"이 인쇄되었습니다.왜 그럴까요?FloatView를 UIView의 하위 클래스로 선언했습니다. 문제 없이 FloatView 개체를 UIView 포인터에 할당할 수 있어야 하지 않습니까?
floatView가 UIView에 대한 포인터로 선언되었지만 실제로는 floatView이고 floatTest 메시지를 처리할 수 있어야 합니까?내가 여기서 완전히 벗어난 걸까요?
해결책
실제로 다형성은 예상대로 작동합니다.작동하지 않으면 아무 것도 인쇄되지 않습니다(귀하의 예에서는 0.0000이 인쇄됩니다).문제는 인스턴스가 실제로 응답하는 동안 testFloat:10.0f
메시지는 컴파일러가 메서드 선언을 정적으로 볼 수 없기 때문입니다(예: UIView
클래스는 그러한 메소드를 선언하지 않습니다), 귀하의 메소드가 다음을 수행한다고 가정합니다. ...
인수 및 반환으로 id
.
언제 CGFloat
가변 개수의 인수를 예상하는 메서드에 전달됩니다(...
), 다음으로 승격됩니다. double
.따라서 수신 메소드는 다음과 같이 전달됩니다. double
논쟁을 벌이고 그것이라고 생각한다. float
그리고 제대로 인쇄되지 않습니다.
다음을 변경하여 이 동작을 확인할 수 있습니다. NSLog
행 :
NSLog(@"%f", *(double*)&x);
컴파일러가 메시지를 보낼 때 FloatView*
보다는 UIView*
, 메소드의 정확한 서명을 찾을 수 있습니다.정말 기대되는 걸 알 수 있죠 CGFloat
그리고 그 주장을 홍보하지 않습니다 double
.결과적으로 올바르게 작동합니다.
추가적으로 만약에 UIView*
다음을 수행하는 메서드 선언이 포함되어 있습니다. CGFloat
, 컴파일러는 메서드를 적절하게 호출합니다.요약하면 이는 다형성 문제가 아닙니다.메소드 서명 문제가 누락되었습니다.