2011-12-14 19 views
11

En Objective-c 2.0, ¿por qué las subclases necesitan hacer referencia a variables de instancia en clases principales utilizando la palabra clave self?Heredar variables de instancia en Objective-c

Considere este ejemplo:

// a.h 
@interface MyClass : NSObject 
@property (nonatomic, retain) Object *myObject; 
@end 

// a.m 
@implementation MyClass 
@synthesize myObject; 
@end 


// b.h 
@interface AnotherClass : MyClass 
@end 

// b.m 
@implementation AnotherClass 
- (void) someMethod { 
    // error 
    // Object *obj = myObject; 

    // works 
    // Object *obj = self.myObject; 
} 
@end 
+2

Esto se explica por la respuesta de [Kevin Ballard] (http://stackoverflow.com/a/8511046/) a [¿Cuál es la visibilidad de ivars sintetizados?] (Http://stackoverflow.com/questions/8510464/) desde hace unas horas. –

Respuesta

11

En realidad no se ha definido una variable, es definido un propiedad (que define implícitamente una variable que es privado). Y como la propiedad es solo un método, necesita la sintaxis de punto. Tenga en cuenta que self.property es lo mismo que [self property].

Para solucionar esto, especifique una variable. Le daré un ejemplo donde la variable tiene un nombre diferente al de la propiedad. La mayoría de las personas eligieron el mismo nombre para ambos, pero me gustaría que sean diferentes, así que de inmediato veo cuál se refiere.

// a.h 
@interface MyClass : NSObject { 
    // Instance variables are "protected" by default, except if you 
    // use @private or @public. 
    Object *myObjectVar; 
} 

@property (nonatomic, retain) Object *myObject; 
@end 

// a.m 
@implementation MyClass 
@synthesize myObject = myObjectVar; 
@end 


// b.h 
@interface AnotherClass : MyClass 
@end 

// b.m 
@implementation AnotherClass 
- (void) someMethod { 
    // works 
    Object *obj = myObjectVar; 

    // works 
    obj = self.myObject; 

    // the same as self.myObject 
    obj = [self myObject]; 
} 
@end 

nota la diferencia cuando se asigna : si se asigna a la variable de objeto no se conserva automáticamente. Pero se mantiene si se utiliza la propiedad:

myObjectVar = someObject; // not retained, old object not released! 
self.myObject = someObject; // old object released, new object retained 
[self setMyObject:someObject]; // same as the line above 

Editar: mencionó que las variables de instancia sintetizados son privados por defecto, como se ha señalado por @ Jason Coco. Y @NSGod tiene razón en que las variables de instancia normales son protegidas de forma predeterminada en lugar de pública, se corrigió eso.

+1

las propiedades '@ sintetizadas' realmente crean un ivar de su nombre, pero sintetizan un '@ private' ivar. Responde las obras porque ha creado específicamente el ivar y le ha asignado el sintetizador con un nivel de acceso menos restrictivo, no porque los sintetizadores no generen ivars. –

+0

No he dicho que los sintetizadores no generen ivars, ¿verdad? Ver mi primera oración. Pero gracias por aclarar que son privados. – DarkDust

+0

Oh, tienes razón. Lo leí mal en mi prisa omitiendo el paréntesis, ¡lo siento! –

8

No lo hacen, siempre que declare una variable de instancia en la superclase, en lugar de confiar en la capacidad del nuevo motor de sintetizar la variable de instancia (además de sintetizar los métodos de acceso). Consulte The Objective-C Programming Language: Runtime Difference para obtener más información sobre la síntesis de variables de instancia.

Por ejemplo, para poder hacer referencia a la variable de instancia directamente, que había necesidad de cambiar lo siguiente:

@interface MyClass : NSObject 
@property (nonatomic, retain) Object *myObject; 
@end 

a:

@interface MyClass : NSObject { 
// there is an implied @protected directive here 
    Object *myObject; 
} 

@property (nonatomic, retain) Object *myObject; 

@end 

Por defecto, las variables de instancia son @protected , lo que significa que la clase y cualquier subclase pueden acceder a las variables de instancia directamente. @protected ivars difieren de @public ivars en que no se puede acceder usando ->. @private ivars solo puede accederse por la clase que los declara. Ver The Objective-C Programming Language: The Scope of Instance Variables para más información.

Cuestiones relacionadas