2009-06-08 21 views

Respuesta

8

La razón es que puede calcular las compensaciones de variables para las subclases.

@interface Bird : NSObject { 
    int wingspan; 
} 
@end 
@interface Penguin : Bird { 
    NSPoint nestLocation; 
    Penguin *mate; 
} 
@end 

Sin conocer la estructura de la clase "Bird", la clase "Pingüino" no puede calcular el desplazamiento de sus campos desde el principio de la estructura. La estructura pingüino se ve algo así como esto:

struct Penguin { 
    int refcount; // from NSObject 
    int wingspan; // from Bird 
    NSPoint nestLocation; // from Penguin 
    Penguin *mate; // from Penguin 
} 

Esto tiene un efecto secundario: si cambia el tamaño de una clase en una biblioteca, romper todas las subclases de aplicaciones que enlazan con esa biblioteca. Las nuevas propiedades trabajan alrededor de este problema.

6

Aunque se declaran en el archivo de encabezado, todas las variables de instancia en Objective-C tienen @protected access de manera predeterminada. Esto significa que la variable es accesible dentro de la clase que lo declara y cualquier clase que hereda de esa clase.

Aquí está la documentación de Apple en la definición de una clase Objective-C: Defining Classes

Aviso la sección titulada "El ámbito de las variables de instancia".

3

Tomado de la sección de la documentación de Apple en la definición de las clases de Objective-C, The Role of the Interface:

Although instance variables are most naturally viewed as a matter of the implementation of a class rather than its interface, they must nevertheless be declared in the interface file. This is because the compiler must be aware of the structure of an object where it’s used, not just where it’s defined.

6

creo que es una cuestión técnica. Si lo entiendo correctamente, una clase de Objective-C es simplemente una estructura C de lujo. Y para que se use una estructura, debe conocerse su tamaño. (Al igual que, de lo contrario, sizeof() funcionaría)

+0

Son sólo las estructuras de C , ni siquiera los de lujo :-) así que algo como anObject-> anIVar funciona bien. Desafortunadamente, el tiempo de ejecución heredado permite este tipo de acceso incluso en variables @private y simplemente vomita una advertencia del compilador: -/ –

2

Tenga en cuenta que en el nuevo Objective C 2.0 "Modern Runtime" (disponible en aplicaciones de iPhone y Mac OS X 10.5 de 64 bits) no necesita especificar los ivars, puede especificar las propiedades y luego usar @synthesize para generar los ivars.

Esto se debe a que en Modern Runtime, los ivars tienen un símbolo de indirección global que contiene el desplazamiento para el ivar. Esto también resuelve el problema de la clase base frágil, permitiendo que los ivars sean reordenados y agregados sin requerir la recompilación de subclases (eliminar o renombrar ivars aún puede causar errores de enlace).

Sin embargo, usted todavía tiene que enumerar las propiedades en la interfaz principal, por lo que no parece haber ninguna manera de ocultar por completo ivars privado que es desafortunado. No puede, por ejemplo, usar una propiedad y @synthesize en una categoría.

+0

Puede, sin embargo, declarar una propiedad en una continuación y @synthesize en la @implementation principal. –

5

En caso de que alguien se tropieza con esta pregunta - como de XCode 4.2 con el compilador LLVM, se puede declarar variables de instancia en el @implementation usando la siguiente notación corsé:


@interface SomeClass : NSObject 
@end 

@implementation SomeClass { 
    NSString *myInstanceVariable_; 
} 

- (void)moreMethods {} 
@end 

Las variables de instancia general, no debe ser parte de la interfaz pública declarada de su clase: son detalles de implementación.

Sin embargo, ASEGÚRESE a definir sus variables de instancia dentro de las llaves o de lo definiremos una variable global que no tiene relación con la instancia del objeto:


@implementation SomeClass 
    NSString *whoopsGlobalVariable_; 

- (void)moreMethods {} 

@end 
+0

Acabo de investigar esto. Parece, por mis pruebas hasta ahora, que GCC no hará esto; da un error: "especificación de variable de instancia inconsistente". Solo compila con LLVM. Véase también [Declarar variables en @implementation] (http://stackoverflow.com/questions/7946998/declaring-variables-in-implementation). –

+1

Correcto, requiere el compilador LLVM moderno. – sickp

Cuestiones relacionadas