[英]In Objective-C does it make sense to declare a readonly property in a category?
假设我有Tree.h
和Tree+Extensions.h
。 我知道如果我在Tree+Extensions.h
声明@property (nonatomic) NSString *color
然后访问它,它将崩溃,并且我可以使用objc_getAssociatedObject
和objc_setAssociatedObject
获得类似于该功能的东西。
但是,我也看到了这个:
// Tree+Extensions.h
@interface Tree (Extensions)
@property (nonatomic, readonly) NSString *color;
@end
// Tree+Extensions.m
@implementation Tree (Extensions)
- (NSString *)color {
return @"green";
}
@end
请注意,类别中的属性声明为readonly
,并且accessor方法返回可以计算的内容。
我已经看到这个代码工作了,但是想知道为什么这比仅仅在头文件中声明访问器方法更可取。
让我们首先忽略这是一个类别并且只是谈论这个事实:
@interface Tree
@property (nonatomic, readonly) NSString *color;
@end
@implementation Tree
- (NSString *)color {
return @"green";
}
@end
据我了解,你的问题是:它与此之间的区别是什么:
@interface Tree
- (NSString *)color;
@end
@implementation Tree
- (NSString *)color {
return @"green";
}
@end
从完全实用的角度来看, 没有区别。 人们习惯于声明属性,但实际上这两个声明具有完全相同的效果 - 即,在任何一种情况下,调用者(任何已导入界面的人)都可以[aTree color]
说[aTree color]
或aTree.color
。 属性用法( aTree.color
) 是方法调用[aTree color]
,反之亦然。 即使只声明了color
方法 (不是属性),调用者也可以说 aTree.color
。 这就是为什么,例如,说myArray.count
是合法的(和常见的),即使NSArray的count
没有被声明为属性(它只是一个方法)。 反之亦然 ,即使将navigationController
声明为属性,也可以说[myViewController navigationController]
是合法的(也是常见的)。
现在,在大多数情况下,声明属性的原因是为了让编译器合成相应的实例变量和相应的方法实现。 但在这种情况下,这一切都没有发生; 没有实例变量,也没有要合成的getter(已经明确写过)。
因此,总而言之,让我们现在回到原始问题并总结:您不能使用命名类别(如Tree (Extensions)
)将实例变量添加到现有类。 正如Apple所说 :
在类别接口中包含属性声明是有效的语法,但是不可能在类别中声明其他实例变量。 这意味着编译器不会合成任何实例变量,也不会合成任何属性访问器方法。
好吧,在这种情况下,你不是在现有类中添加一个实例变量,而你并没有尝试合成“getter”: readonly
属性声明由现有的 “getter”方法支持,正如你正确地说的那样,计算整块布料的结果。 因此,财产声明虽然毫无意义,但却完全合法有效:它只是声明了“吸气”方法。
使用您编写的代码,即使是在类中,您也无法调用setColor:
当您想要返回未被ivar支持的内容(例如计算)并且您不想要时,这可能是有意义的揭露外面的世界。
答:这是首选,因为您不需要从课外访问此属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.