Objective-C实例变量访问器方法
我试图用Objective-C编程语言更详细地了解 现在我有一个关于设置值时调用Objective-C实例变量访问器方法,objective-c,Objective C,我试图用Objective-C编程语言更详细地了解 现在我有一个关于设置值时调用[self]的问题 Apple文档中说“如果不使用self,则直接访问实例变量。(…) 所以假设我有一个dog对象,它有一个实例变量NSString*name 我像这样为该实例变量创建setter,而不使用[self]关键字: (void)setName:(NSString *)_name { name = _name; } 当我使用[self]关键字创建setter时,它如下所示: (void)setName
[self]
的问题
Apple文档中说“如果不使用self,则直接访问实例变量。(…)
所以假设我有一个dog对象,它有一个实例变量NSString*name
我像这样为该实例变量创建setter,而不使用[self]
关键字:
(void)setName:(NSString *)_name
{
name = _name;
}
当我使用[self]关键字创建setter时,它如下所示:
(void)setName:(NSString *)_name
{
self->name = _name;
}
// _name is the instance variable
- (void)setName:(NSString *)name
{
[name retain];
[_name release];
_name = name;
}
在main方法中,我创建了一个新的dog对象,并设置并返回其名称值:
Dog *myDog = [[Dog alloc] init];
myDog.name = @"Yoda";
NSLog(@"name of the dog: %@", myDog.name);
在这两种情况下,我都会得到一个返回值Yoda。但是从技术上讲,有[self]和没有[self]的实例变量调用之间的区别在哪里呢?是不是我只调用了相同的变量(内存),而没有使用setter方法?您的两个示例之间没有区别,在这两种情况下,您都直接修改了实例变量 self的意思是
self.name
,它使用setter方法[self-setName:someValue]代码>
self->name
只是表示它正在访问一个实例变量,所以
self->ivar = someVal;
//is the same as
ivar = someVal;
self
是对对象本身的隐式引用,通常仅当参数和实例变量具有相同名称时才需要指定它,例如,如果您有:
(void)setName:(NSString *)name
{
self->name = name; // self used here to differentiate between param and ivar
}
但是,您需要注意命名约定和方法的实现:
通常,前导下划线用作命名实例变量的约定,而不是传递给方法的参数
为了设置NSString*
对象,通常需要保留它,以获得对象的所有权并避免它被释放(这将在以后访问它时导致异常)
因此,您的setName
方法应该更像这样:
(void)setName:(NSString *)_name
{
self->name = _name;
}
// _name is the instance variable
- (void)setName:(NSString *)name
{
[name retain];
[_name release];
_name = name;
}
只有当您使用MRR而不是ARC时,这才是正确的,但是您没有指定,所以我假设您使用的是MRR。self.name
与[self-setName:name]
相同,而不是self->name
@特洛伊木马。如果正确,这是我说的,我将进行编辑以使其更清晰,因此在这两种情况下,我都在相同的变量上操作(也就是说,与我在内存中分配的位置相同)?@MrBr正确,您的两个示例都直接访问ivar。使用self.myProperty=…的区别在于您得到了合成的setter(假设您没有重写它们)这意味着您可以在非ARC环境中进行内存管理,以及其他类似KVO Notifications的功能。感谢您对第一部分的解释。我不明白您为什么在setter中保留name
对象。我想我只需要在set中使用name
对象在我将它分配给实例变量\u name
之后,它可以被释放,而\u name
应该保留以供以后使用?@MrBr这一切都取决于您是否使用了自动引用计数(ARC)。如果是这样,您就不必担心,您的版本也会很好。