iphone - ejemplos - Llamar a un método en un objeto no inicializado(puntero nulo)
ejemplos de punteros en c# (3)
Desde el sitio de Greg Parker :
Si ejecuta LLVM Compiler 3.0 (Xcode 4.2) o posterior
Messages to nil with return type | return Integers up to 64 bits | 0 Floating-point up to long double | 0.0 Pointers | nil Structs | {0} Any _Complex type | {0, 0}
- ¿Cuál es el comportamiento normal en Objective-C si llama un método en un objeto (puntero) que es nulo (quizás porque alguien olvidó inicializarlo)? ¿No debería generar algún tipo de error (falla de segmentación, excepción de puntero nulo ...)?
- Si se trata de un comportamiento normal, ¿hay alguna manera de cambiar este comportamiento (configurando el compilador) para que el programa genere algún tipo de error / excepción en el tiempo de ejecución?
Para dejar más claro de lo que estoy hablando, aquí hay un ejemplo.
Tener esta clase:
@interface Person : NSObject {
NSString *name;
}
@property (nonatomic, retain) NSString *name;
- (void)sayHi;
@end
con esta implementación:
@implementation Person
@synthesize name;
- (void)dealloc {
[name release];
[super dealloc];
}
- (void)sayHi {
NSLog(@"Hello");
NSLog(@"My name is %@.", name);
}
@end
En algún lugar del programa, hago esto:
Person *person = nil;
//person = [[Person alloc] init]; // let''s say I comment this line
person.name = @"Mike"; // shouldn''t I get an error here?
[person sayHi]; // and here
[person release]; // and here
Un mensaje enviado a un objeto nil
es perfectamente aceptable en Objective-C, se trata como un no-op. No hay forma de marcarlo como un error porque no es un error, de hecho puede ser una característica muy útil del lenguaje.
De los docs :
Envío de mensajes a cero
En Objective-C, es válido enviar un mensaje a nil, simplemente no tiene ningún efecto en el tiempo de ejecución. Hay varios patrones en Cocoa que aprovechan este hecho. El valor devuelto por un mensaje a nil también puede ser válido:
Si el método devuelve un objeto, entonces un mensaje enviado a
nil
devuelve0
(nil
), por ejemplo:
Person *motherInLaw = [[aPerson spouse] mother];
Si el
spouse
esnil
, entonces se envía a lamother
anil
y el método devuelvenil
.Si el método devuelve cualquier tipo de puntero, cualquier número entero escalar de tamaño inferior o igual a
sizeof(void*)
,float
,double
,long double
olong long
, entonces un mensaje enviado anil
devuelve0
.Si el método devuelve una
struct
, tal como se define en la Guía de funciones de la función ABI de Mac OS X, para que se devuelva en los registros, un mensaje enviado anil
devuelve0.0
para cada campo en la estructura de datos. Otros tipos de datosstruct
no se llenarán con ceros.Si el método devuelve algo distinto a los tipos de valores antes mencionados, el valor de retorno de un mensaje enviado a cero no está definido.
Una cosa que debe tener claro es que en Objective-C, no llama a un método en un objeto, envía un mensaje a un objeto. El tiempo de ejecución encontrará el método y lo llamará.
Desde las primeras versiones de Objective-C, un mensaje a nil siempre ha sido una operación segura no operativa que devuelve nada. Hay un montón de código que depende de este comportamiento.