Domanda

Oggi ho riscontrato uno strano problema. Ho creato una sottoclasse di UIView e ho aggiunto solo 1 metodo al codice modello fornito da xcode.

@interface FloatView : UIView {

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

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

Quindi nella mia appDelegate avevo un codice come questo:

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

Abbastanza semplice, vero? Cosa dovrebbe stampare? Ho pensato che sarebbe qualcosa di simile a "10.0000", ma no, stampa "0,000000".

Ho lottato con questo per ore, cercando di capire cosa stavo facendo di sbagliato, e poi ho cambiato il codice nella mia appDelegate in

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

Solo allora ha stampato il previsto "10.0000". Perché è così? Ho dichiarato FloatView come sottoclasse di UIView, non dovrei essere in grado di assegnare un oggetto FloatView a un puntatore UIView senza problemi?

Anche se floatView è stato dichiarato un puntatore a un UIView, è davvero un floatView e dovrebbe essere in grado di gestire il messaggio floatTest? Sono totalmente fuori base qui?

È stato utile?

Soluzione

In realtà, il polimorfismo funziona come previsto. Se non avesse funzionato, non sarebbe stato stampato nulla (nel tuo esempio, 0,0000 è in fase di stampa). Il fatto è che l'istanza in realtà risponde al messaggio testFloat: 10.0f , poiché il compilatore non può vedere staticamente la dichiarazione del metodo (poiché la classe UIView non dichiara tale un metodo), presuppone che il tuo metodo prenda ... come argomento e restituisca id .

Quando CGFloat viene passato a un metodo che prevede un numero variabile di argomenti ( ... ), viene promosso a double . Pertanto, al metodo di ricezione viene passato un argomento double e pensa che sia un float e che non venga stampato correttamente.

È possibile verificare questo comportamento modificando la riga NSLog in:

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

Quando il compilatore invia il messaggio a FloatView * anziché a UIView * , può trovare la firma esatta del metodo. Può vedere che si aspetta davvero CGFloat e non promuove l'argomento a double . Di conseguenza, funziona correttamente.

Inoltre, se UIView * contenesse la dichiarazione del metodo che ha preso un CGFloat , il compilatore chiamerebbe il metodo in modo appropriato. Riassumendo, questo non è un problema di polimorfismo; è un problema di firma del metodo mancante.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top