我正在研究Big Nerd Ranch的Objective C编程书。 我看到了如下代码:
@interface BNREmployee : BNRPerson
{
NSMutableArray *_assets;
}
@property (nonatomic) unsigned int employeeID;
@property (nonatomic) unsigned int officeAlarmCode;
@property (nonatomic) NSDate *hireDate;
@property (nonatomic, copy) NSArray *assets;
-(double)yearsOfEmployment;
-(void)addAsset:(BNRAsset *)a;
-(unsigned int)valueOfAssets;
在此代码中,为什么要在界面下声明NSMutableArray *_assets
?这与宣称它是一种财产有什么不同,它的用途是什么?
最后,我看到一个属性中有一个NSArray *assets
。这与NSMutableArray *_assets
基本相同吗?
答案 0 :(得分:2)
在这里,您要声明一个名为_assets
的实例变量:
@interface BNREmployee : BNRPerson {
NSMutableArray *_assets;
}
您现在可以在类的实现中使用此变量:
_assets = @[ @1, @2, @4 ].mutableCopy;
NSLog(@"The Answer is %@.", _assets[0]);
但是,实例变量在Objective-C中是私有的,如果您不想要任何其他内容来访问它,这是很好的。但是,如果您需要其他课程来访问和/或更改assets
?
在大多数情况下,您需要使用iVar属性。
通过使用属性,我们自动创建setter和getter,这意味着可以覆盖它以进行自定义并由其他类使用(如果放在标题.h
文件中)。
@property (nonatomic, assign) NSMutableArray *assets;
NSMutableArray只是NSArray的可变(可编辑)对应物,它意味着我们可以通过插入新的,删除旧的和移动索引来修改数组的值。
答案 1 :(得分:1)
我不确定他们为什么这样做,但作为一般的良好做法,你不应该自己这样做。应该为该类的公共接口保留头文件。只是把那个类的调用者和用户真正需要看到的东西放在那里,通常是属性,方法和extern
常量。
然后问题就变成了实现是使用属性还是常规实例变量。这主要是基于偏好的。有些人声明了一切的属性,根本不使用普通的ivars。其他人在他们想要为有问题的变量声明自定义setter / getter时,只使用ivars作为所有内容和属性。我在后一个阵营,但如果一切都只是一个财产,那么可以说更清晰,更容易阅读。
修改强>
我误读了代码。我上面所说的通常是正确的,但是他们在那里做的是暴露出与底层数据不同的API。现在编辑我的答案。
当您声明没有自定义@synthesize
的属性并且没有覆盖setter和getter(如果它们适用)时,将使用前面的下划线创建基础变量。他们在这里做的是在公共API中返回NSArray
以确保在内部使用NSMutableArray
时不修改内部变量。
我会说,一般情况下,变量声明(NSMutableArray *_assets;
)仍然应该放在实现文件中。调用者可能不需要知道它在引擎盖下是可变的。
实际上已经存在许多现有问题。这是一个包含多个搜索查询的搜索查询: https://stackoverflow.com/search?q=mutable+ivar+immutable+property
答案 2 :(得分:0)
关键思想是实例变量的类型与属性声明的类型不同:它是可变的,而属性声明是不可变的。