我正在尝试使用Objective-C编程语言了解更多细节。
现在我有一个关于在设置值时调用[self]
的问题。
苹果公司的文档中写道:"如果你不使用self.,你可以直接访问实例变量。(…)"
所以假设我有一个dog对象,它有一个实例变量NSString *name
。
我为这个实例变量创建了一个setter,就像这样,而不使用[self]
关键字:
(void)setName:(NSString *)_name
{
name = _name;
}
当我用[self]关键字创建一个setter时,它看起来像这样:
(void)setName:(NSString *)_name
{
self->name = _name;
}
在主方法中,我创建了一个新的dog对象,并设置并返回其名称值:
Dog *myDog = [[Dog alloc] init];
myDog.name = @"Yoda";
NSLog(@"name of the dog: %@", myDog.name);
在这两种情况下,我都会得到Yoda的返回值。但是,从技术上讲,带有和不带有[self]的实例变量调用之间的区别在哪里?是不是我调用了同一个变量(内存)而不使用setter方法?
self
是对对象本身的隐式引用,通常只有当参数和实例变量具有相同名称时,才真正需要指定它,例如,如果您具有:
(void)setName:(NSString *)name
{
self->name = name; // self used here to differentiate between param and ivar
}
然而,您需要小心命名约定和方法的实现:
- 通常,前导下划线用作命名实例变量的约定,而不是传递给方法的参数
- 为了设置
NSString *
对象,通常需要retain
它,以便获得对象的所有权并避免它被释放(这将在以后访问它时导致异常)
因此,您的setName
方法应该更像这样:
// _name is the instance variable
- (void)setName:(NSString *)name
{
[name retain];
[_name release];
_name = name;
}
只有当您使用MRR而不是ARC时,这才是正确的,但您没有指定,所以我假设您使用的是MRR。
您的两个示例之间没有区别,在这两种情况下,您都是直接修改实例变量
就其本身而言,它是指使用设置方法[self setName:someValue];
的self.name
self->name
只是意味着它正在访问一个实例变量,因此
self->ivar = someVal;
//is the same as
ivar = someVal;