你所提到的每种情况都有适当的应用场景,在实际使用中使用时需要小心,以免出错。我将举个人经历的例子来说明。
子类化以有意覆盖属性
在这种情况下,就像Joe所提到的那样,你最好在覆盖属性之前确切地知道自己在做什么,并且没有其他选择。我个人发现,通常只需覆盖已有属性的一个setter或getter方法即可实现定制,而不是重新声明和合成属性。例如,考虑一个专门的UIView子类,只有具有UIClearColor背景才有意义。为了强制执行此操作,您可以覆盖
-setBackgroundColor:
,只需打印警告消息,然后不调用super的实现即可。我会说我从未有过完全覆盖属性的理由,但我不会说它在某些需要完全劫持现有属性的情况下可能是有用的工具。
私有属性
这比你想象的更有用。私有属性的替代方案是普通的ivar,我们都熟悉。如果这是一个频繁更改的ivar,您最终将得到看起来像这样的代码块:
[_myIvar release], _myIvar = nil;
或者:
[_myIvar release];
_myIvar = [someValue retain];
虽然看起来不错,但是像这样的内存管理样板代码很快就会变得非常老套。或者,我们可以将上面的示例实现为一个私有属性,具有保留语义。这意味着,无论如何,我们只需要:
self.myIvar = someValue;
这样做可以让阅读和输入更加轻松,您说得没错,由于这个属性对于其他人来说是不可见的,所以它可能会被子类意外覆盖。在Objective-C开发中,这是一种固有的风险,但您可以采取措施使该风险变得微乎其微。这些措施是通过以可预测的方式修改私有属性名称的变化来实现的。在这里,您可以选择无限的方法:例如,您可以制定一个个人策略,以自己的缩写和下划线作为私有属性名称的前缀。对于我来说,我会得到类似于
mw_ivar
,以及相应的
-setMW_ivar:
和
-mw_ivar
访问器。是的,有统计学上的可能性,某人会意外地覆盖该名称,但事实上他们不会这么做。特别是如果您有一种向那些可能使用您的代码的人发布您的实践的方法。而且,我可以肯定地说,苹果公司并没有去制造那些被混淆的私有属性,因此在这方面您也是安全的。
公共只读,私有可读写
这只是标准做法。您说得对,这很有用,而且也不危险,因为属性在头文件中。任何意外覆盖它的人只能怪自己。
id
的属性。在子类上,您可以通过重新声明属性(例如NSString *
)来使其更具体,并在子类中使用@dynamic propertyName
来告诉编译器使用父类中的存储。 - Sandy Chapman