在Objective-c 2.0中,为什么子类需要使用self
关键字在父类中引用实例变量?
考虑这个例子:
// 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
答案 0 :(得分:13)
您实际上没有定义变量,您只定义了一个属性(它隐式定义了一个私有变量)。由于属性只是方法,因此需要点语法。请注意,self.property
与[self property]
相同。
要解决此问题,请指定一个变量。我将举例说明变量的名称与属性不同。大多数人为两者选择了相同的名称,但我喜欢让它们有所不同,所以我立刻就会看到它的含义。
// 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
注意分配时的区别:如果分配给变量,则不会自动保留对象。但如果您使用该属性,它将被保留:
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
编辑:提到合成的实例变量默认是私有的,如@Jason Coco所述。并且@NSGod是正确的,正常的实例变量默认是受保护的而不是公共的,修复了它。
答案 1 :(得分:8)
如果您实际在超类中声明了一个实例变量,它们不会,而不是依赖新运行时的合成实例变量的能力(除了合成访问器方法)。有关实例变量合成的更多信息,请参阅The Objective-C Programming Language: Runtime Difference。
例如,为了能够直接引用实例变量,您需要更改以下内容:
@interface MyClass : NSObject
@property (nonatomic, retain) Object *myObject;
@end
为:
@interface MyClass : NSObject {
// there is an implied @protected directive here
Object *myObject;
}
@property (nonatomic, retain) Object *myObject;
@end
默认情况下,实例变量为@protected
,这意味着类和任何子类都可以直接访问实例变量。 @protected
ivars与@public
ivars的不同之处在于您无法使用->
访问它们。 @private
ivars只能由声明它们的类访问。有关详细信息,请参阅The Objective-C Programming Language: The Scope of Instance Variables。