Objective-c中的“实例variables”和“属性”有什么不同?
Objective-c中的“实例variables”和“属性”有什么不同?
我对此不太确定。 我认为一个“属性”是一个具有访问方法的实例variables,但我可能认为是错误的。
财产是一个更抽象的概念。 一个实例variables实际上只是一个存储槽,就像一个结构中的槽。 通常情况下,其他对象不应该直接访问它们。 另一方面,属性是可以访问的对象的一个属性(它听起来很模糊而且应该是这样的)。 通常一个属性会返回或者设置一个实例variables,但是它可以使用多个或者全部的数据。 例如:
@interface Person : NSObject { NSString *name; } @property(copy) NSString *name; @property(copy) NSString *firstName; @property(copy) NSString *lastName; @end @implementation Person @synthesize name; - (NSString *)firstName { [[name componentsSeparatedByString:@" "] objectAtIndex:0]; } - (NSString *)lastName { [[name componentsSeparatedByString:@" "] lastObject]; } - (NSString *)setFirstName:(NSString *)newName { NSArray *nameArray = [name componentsSeparatedByString:@" "]; NSArray *newNameArray [[NSArray arrayWithObjects:newName, nil] arrayByAddingObjectsFromArray:[nameArray subarrayWithRange:NSMakeRange(1, [nameArray size]-1)]]; self.name = [newNameArray componentsJoinedByString:@" "]; } - (NSString *)setLastName:(NSString *)newName { NSArray *nameArray = [name componentsSeparatedByString:@" "]; NSArray *newNameArray [[nameArray subarrayWithRange:NSMakeRange(0, [nameArray size]-2)] arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:newName, nil]]; self.name = [newNameArray componentsJoinedByString:@" "]; } @end
(注:上面的代码是错误的,因为它假设名称已经存在,并且至less有两个组件(比如“Bill Gates”而不是“Gates”),我认为修复这些假设会使代码的实际点不太清楚,所以我只是在这里指出来,所以没有人无辜地重复这些错误。)
一个属性是一个友好的方式来实现一个getter / setter的一些价值,其他有用的function和语法。 一个属性可以由一个实例variables支持,但是你也可以定义getter / setter来做一些更dynamic的事情,例如你可以定义一个string的lowerCase属性来dynamic创build结果,而不是返回某个成员的值variables。
这是一个例子:
// === In your .h === @interface MyObject { NSString *propertyName; } // ... @property (nonatomic, retain) NSString *propertyName; // === In your .m @implementation === @synthesize propertyName /* = otherVarName */;
@property
行定义了一个名为NSString *
types的propertyName propertyName
。 这可以使用以下语法来获取/设置:
myObject.propertyName = @"Hello World!"; NSLog("Value: %@", myObject.propertyName);
当你分配或从myObject.propertyName
读你真的调用对象的setter / getter方法。
@synthesize
行告诉编译器为你生成这些getter / setters,使用与该属性同名的成员variables来存储值(或者如果你在注释中使用语法,则使用otherVarName
)。
与@synthesize
一起,您仍然可以通过定义自己的getter / setter来覆盖其中一个getter / setter。 这些方法的命名约定是setPropertyName:
用于getter的setter和propertyName
(或getPropertyName
,不是标准的)。 另一个仍然会为你生成。
在你的@property
行中,你可以在parens中定义一些属性,这些属性可以自动执行线程安全和内存pipe理。 默认情况下,一个属性是primefaces的,这意味着编译器会使用合适的锁包装@synthesiz
ed get / set调用来防止并发问题。 您可以指定nonatomic
属性来禁用此属性(例如在iPhone上,您希望将大多数属性默认nonatomic
)。
有3个属性值可以控制任何@synthesized
setter的内存pipe理。 首先是retain
,它会自动发送到旧的价值的属性,并retain
到新的价值。 这非常有用。
第二个是copy
,它将复制任何值,而不是保留它们。 对NSString使用copy
是一个很好的做法,因为调用者可以传入一个NSMutableString,并将其从你的下面更改。 copy
将创build只有您有权访问的input的新副本。
第三个是assign
直接指针而不调用旧对象或新对象的保留/释放。
最后,您还可以使用readonly
属性来禁用该属性的setter。
我使用接口部分的属性 – 其中对象与其他对象和实例variables的接口是你在类中需要的东西 – 除了你应该看到并操作这些东西外,没有其他的东西。
默认情况下,readwrite属性将由实例variables支持,该实例variables将再次由编译器自动合成。
一个实例variables是一个存在并保存对象的生命值的variables。 用于实例variables的内存在对象首次创build(通过alloc)时被分配,并在对象被释放时被释放。
除非另外指定,否则合成的实例variables与该属性具有相同的名称,但带有下划线前缀。 例如,对于名为firstName的属性,合成的实例variables将被称为_firstName。
以前,人们公开使用属性,私人使用ivars,但是由于几年前,您也可以在@implementation
定义属性来私下使用它们。 但是,如果可能的话,我仍然会使用ivars,因为input的字母更less,根据这篇文章 ,它运行得更快。 这是有道理的,因为属性意味着“沉重”:它们应该从生成的getter / setters或者手写的访问。
但是,在最近的苹果代码中,ivars已经不再使用了。 我猜是因为它更像objc
而不是C/C++
,再加上它更容易使用assign
, nullable
等属性。