当前位置:编程学习 > JAVA >>

深刻理解属性、getter及setter

 
 
对于有Mac开发经验的iPhone开发者,可能对O-C的注解“@property”已经习以为常了。但对于从其他开发平台(Java或者Symbian)迁移过来的iPhone开发者,“@property”仍然有点麻烦。为了使这些人不再犯我一样的错误,本文简单探讨了变量及属性,以及它们所采用的内存管理。
 
首先来看一个简单类:
 
 
 
//MyClass.h file
@inte易做图ce MyClass: NSObject
{
    NSString *text;
}
 
-(void) init;
-(void) logText;
@end
 
//MyClass.m file
@implementation MyClass
 
- (void)init
{
    text = @\"sometext\";
}
 
- (void)logText
{
   NSLog(@\"%@\", text);
}
@end
 
 
这个类十分简单。它唯一的成员就是text,一个NSString。text变量在init方法中初始化,在logText方法中被引用。
就目前而言,text变量中存储的是常量值,我们无须关心它的内存管理。但在真正的程序中,我们可能会想在运行时改变text的值,因此需要为它设计getter和setter方法:
 
 
//MyClass.h file
@inte易做图ce MyClass: NSObject
{
    NSString *text;
}
 
-(void) init;
-(void) logText;
-(NSString*) text;
-(void) setText:(NSString *)textValue;
@end
 
//MyClass.m file
@implementation MyClass
 
- (void)init
{
    text = @\"sometext\";
}
 
- (void)logText
{
   NSLog(@\"%@\", text);
}
 
-(NSString*) text
{
    return text;
}
 
-(void) setText:(NSString *)textValue
{
    if (textValue !=text)
    {
       [textValue retain];
       [text release];
       text = textValue;
    }
}
 
-(void)dealloc
{
    [text release];
    [super dealloc];
}
 
@end
 
 
接下来,我们需要:
一、添加一个方法,读取当前的text属性:
 
NSString *theTextValue = [obj text];
 
 
(假设 "obj" 是一个MyClass实例)
 
 这个方法很简单 - 仅仅是返回text属性值。 
二、在另一个方法中,改变text属性:
 
 
    [obj setText:newStringValue];
 
 
(假设 "obj" 是一个MyClass实例, "newStringValue" 是一个 NSString).
在setText:方法中,由于我们无法确定newStringValue到底是不是一个常量——它可能是任何NSString值,包括在堆中分配的NSString。因此,我们要“retain”这个(将要赋值给text的)对象,以确保这个对象能够和MyClass对象的生命周期一样长。同样,对于已经被替换掉的旧有值,我们不应当再持有它,因此我们释放了它。if语句的使用,是为了减少不必要的赋值——当然,你也可以不用它:
 
 
-(void) setText:(NSString *)textValue
{
    [textValue retain];
    [text release];
    text = textValue;
}
 
 
即使textValue和text值相同,代码也会被执行,因为我们先在引用计数器上+1,然后再减1。注意,这种写法是错误的:
-(void) setText:(NSString *)textValue
{
    [text release];
    [textValue retain];
    text = textValue;
}
 
 
 
这是因为,当“输入”值和要“持有”的值指向了同一个NSString的情况下,会导致字符串最终将被deallocated——第1句代码有可能将引用计数减为0,导致对象被仍会堆里。第2句代码试图去retain这个已经释放的对象(由于二者是同一个)。这种情况不一定发生,但却是一个隐患。
最后,我们实现dealloc方法,在其中释放text对象。我们既然retain了某些东西,就需要记得release它,就好比人临死的时候,要记得把借的书还给图书馆。
值得注意的是,进行空赋值这些代码仍然工作得很好。O-C有个奇怪的特点,允许向nil发送消息(比如release和retain消息)而不会出任何错误。类似于++ 中可以释放一个null指针。
 
现在,更有趣的事情来了。我们将加入第2个成员变量,以及它的getter和setter。很快你就会看到将发生什么。
 
 
 
//MyClass.h file
@inte易做图ce MyClass: NSObject
{
    NSString *text;
    int value;
}
 
-(void) init;
-(void) logText;
-(NSString*) text;
-(void) setText:(NSString *)textValue;
-(int) value;
-(void) setValue:(int*)intValue;
@end
 
//MyClass.m file
@implementation MyClass
 
- (void)init
{
    text = @\"sometext\";
    value = 2;
}
 
- (void)logText
{
   NSLog(@\"%@\", text);
}
 
-(NSString *) text
{
    return text;
}
 
-(void) setText:(NSString *)textValue
{
    if (textValue !=text)
    {
       [textValue retain];
       [text release];
       text = textValue;
    }
}
 
-(int) value
{
    return value;
}
 
-(void) setValue:(int)intValue
{
    value = intValue;
}
 
-(void)dealloc
{
    [text release];
    [super dealloc];
}
 
@end
 
 
这次,我们简单地加入了一个整型变量以及setter/getter方法。但这次,我们不需要retain 和release 。因为整型不是在堆中分配的-它直接存储在MyClass中。我们可以这样干:
 
    NSString *s = [objtext];
    [objsetText:@\"new string\"];
    int i = [obj value];
    [obj setValue:3];
 
 
 
现在,类似的getter/setter方法在O-C中实在是多得让人写不胜写。因此O-C也提供了更简单的方式为我们自动生成这些方法。我们可以将上述代码修改为:
//MyClass.h file
@inte易做图ce MyClass: NSObject
{
    NSString *text;
    int value;
}
 
@property(nonatomic, retain) NSString *text;
@property(nonatomic, assign) int value;
 
-(void) init;
-(void) logText;
@end
 
//MyClass.m file
@implementation MyClass
 
@synthesize text;
@synthesize value;
 
- (void)init
补充:软件开发 , Java ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,