Pregunta

Hoy me encontré con un problema extraño. Creé una subclase de UIView y agregué solo 1 método al código de plantilla proporcionado por xcode.

@interface FloatView : UIView {

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

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

Luego, en mi appDelegate, tenía un código como este:

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

Bastante simple, ¿verdad? ¿Qué debería imprimir esto? Pensé que sería algo así como "10.0000", pero no, imprime "0.000000".

Luché con esto durante horas, tratando de descubrir qué estaba haciendo mal, y luego cambié el código de mi aplicación Delegar a

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

Solo entonces, imprimió el esperado "10.0000". ¿Por qué esto es tan? He declarado FloatView como una subclase de UIView, ¿no debería poder asignar un objeto FloatView a un puntero UIView sin problemas?

Aunque floatView se declaró puntero a una UIView, ¿es realmente un floatView y debería poder manejar el mensaje floatTest? ¿Estoy totalmente fuera de lugar aquí?

¿Fue útil?

Solución

En realidad, el polimorfismo está funcionando como se esperaba. Si no funcionó, no se habría impreso nada (en su ejemplo, se está imprimiendo 0.0000). La cuestión es que, aunque su instancia realmente responde al mensaje testFloat: 10.0f , ya que el compilador no puede ver estáticamente la declaración del método (ya que la clase UIView no declara un método), se supone que su método toma ... como argumento y devuelve id .

Cuando CGFloat se pasa a un método que espera un número variable de argumentos ( ... ), se promueve a double . Por lo tanto, el método de recepción pasa un argumento double y piensa que es un float y no se imprime correctamente.

Puede verificar este comportamiento cambiando la línea NSLog a:

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

Cuando el compilador envía el mensaje a FloatView * en lugar de a un UIView * , puede encontrar la firma exacta del método. Puede ver que realmente espera CGFloat y no promueve el argumento de double . Como resultado, funciona correctamente.

Además, si UIView * contenía la declaración del método que tomó un CGFloat , el compilador llamaría al método apropiadamente. Para resumir, este no es un problema de polimorfismo; es un problema de firma de método faltante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top