2010-04-23 11 views
31
  1. ¿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 ...)?
  2. 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 que quede más claro de lo que estoy hablando, he aquí un ejemplo.Llamar a un método en un objeto no inicializado (puntero nulo)

Tener esta clase:

@interface Person : NSObject { 

    NSString *name; 

} 

@property (nonatomic, retain) NSString *name; 

- (void)sayHi; 

@end 

con esta aplicació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 en el 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 

Respuesta

57

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.

Desde el docs:

envío de mensajes a cero

En Objective-C, que es válida para enviar un mensaje a cero; simplemente no tiene ningún efecto en tiempo de ejecución. Hay varios patrones en Cocoa que aprovechan este hecho . El valor devuelto desde un mensaje a cero también puede ser válido:

  • Si el método devuelve un objeto, a continuación, un mensaje enviado a nil rendimientos 0 (nil), por ejemplo:

    Person *motherInLaw = [[aPerson spouse] mother];

    Si aPerson 's spouse es nil, a continuación, mother se envía a nil y laEl métododevuelve nil.

  • Si el método devuelve cualquier tipo de puntero, cualquier escalar número entero de tamaño inferior que o igual a sizeof(void*), un float, un double, un long double, o una long long, a continuación, un mensaje enviado a nil rendimientos 0 .

  • Si el método devuelve un struct, según la definición de la Guía de llamada Función Mac OS X ABI vaya a devolver en registros, a continuación, envía un mensaje a nil vuelve 0.0 para cada campo en la estructura de datos. Otros struct tipos de datos no se llenarán con ceros.

  • Si el método devuelve algo que no sea el valor anteriormente mencionado escribe que el valor de retorno de un mensaje enviado a cero no está definido.

+2

y no estoy al tanto de ninguna manera de cambiar este comportamiento. Es una parte fundamental de la programación con Objective-C/Cocoa. Aprenderás a amarlo. –

+0

El enlace al documento en respuesta está muerto (* Página no encontrada *). – Pang

6

Una cosa que debe tener claro es que en Objective-C, no lo hace llamada 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.

12

De Greg Parker 's site:

Si se ejecuta el compilador LLVM 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} 
Cuestiones relacionadas