2011-04-13 47 views
18

有几种情况可能会覆盖超类的属性。Objective-C中属性覆盖有什么危害?

  1. 您声明具有相同的名称和它的 超的相同属性的属性。(因为如果你改变了 属性你可以得到一个编译器警告 )。而且你可以与伊娃synthesieze 那你创建。什么是 这个用法?或者它有什么危害 它可以做什么?

  2. 如果父类声明类扩展中的属性( 没有名称),那么它在头文件中可能不是 。如果 不知道 头文件中的属性,则可以声明同名 属性,并指定要使用的属性或 类。但是设置者/获取者方法将覆盖 那个“秘密属性”的方法。 我认为这只会造成伤害。但 既然你不知道从头文件 文件,你怎么能避免这种情况?

  3. 您可以将头文件中的属性声明为“只读”,并在 类扩展中重新声明它为 “readwrite”。我认为这是可以做得很好的 情况。

我对这些情况的理解是否正确?我不知道第一种情况和第二种情况能做些什么。但是如果我想避免第一种情况,我可以在声明它之前检查子类是否已经拥有该属性。但是,如果该属性不在公共头文件中,就像在第二种情况下一样,我只是不知道该怎么做。

回答

5

没有为每个你所提到的情况下,适当的地方,在野外不同的使用频率了。你只需要小心不要踩在自己身上。我会用我亲自遇到的例子来说明。

子类故意覆盖属性
在这种情况下,像乔提到的,你最好知道你在做什么,并没有其他的选择,你重写属性之前。我个人发现,通常可以重写一个setter或getter来获得已经存在的属性来实现定制,而不是重新声明和合成属性。例如,考虑一个专门的UIView子类,只有意义才能具有UIClearColor背景。为了执行此操作,您可以覆盖-setBackgroundColor:以仅打印警告消息,然后不调用super的实现。我会说我从来没有理由完全覆盖一个属性,但我不会说在某些情况下它不可能是一个有用的工具,你需要彻底劫持一个现有的属性。

私有财产
这比你给它的功劳更有用。私有财产的替代品是一种简单的酒,我们都很熟悉。如果这是一个与某些频率改变伊娃,你最终会与像这样的代码块:

[_myIvar release], _myIvar = nil; 

或:

[_myIvar release]; 
_myIvar = [someValue retain]; 

虽然它看起来并不太坏,像这样的内存管理样板代码变得非常老,非常快。或者,我们可以使用保留语义将上述示例作为私有属性实现。这意味着,不管是什么,我们只需要:

self.myIvar = someValue; 

这是一段时间后眼睛和手指更容易。你注意到这点是正确的,因为这个属性对于宇宙的其他部分是不可见的,它可能会被一个子类无意中覆盖。在Objective-C中开发时,这是一种固有风险,但您可以采取措施使风险消失得很小。这些措施是以可预测的方式修改您的私人财产的名称的变化。你可以在这里采取无限的道路:比如说,你把它作为一个个人的政策,用你的首字母和下划线来预先给你的私人财产名称。对于我来说,我会得到类似mw_ivar和相应的-setMW_ivar:-mw_ivar访问器。是的,统计上可能有人会出现并意外覆盖该名称,但实际上,他们不会。特别是如果您有将您的实践发布给可能会使用您的代码的人的方法。而且,我可以有把握地说,苹果公司并没有走出去,制造出以这种方式被摧毁的私人财产,所以你在这方面也会很安全。

publicly readonly,Privately Readwrite
这只是标准做法。你说得对,它是有用的,而且它不是危险的,因为该属性在标题中。任何意外超越它的人都只能责怪自己。

+0

另一个用例在这个很好的答案中是缺少的,用于在子类上指定更具体的类型。即父级上有一个“id”类型的属性。在子类上,可以通过重新声明属性(如'NSString *'),然后在子类中使用'@dynamic propertyName'来通知编译器使用父级存储。 – 2016-05-19 11:06:13

0

问得好

  1. 使用的,这是你作为 开发者应该知道你是 在这一点上做的和需要 自定义添加到基类 性质是什么。既然你知道你在做什么 你会正确地呼吁 super的实施,除非 你有充分的理由不要。 决定不叫超级可能是 有害,特别是在 情况下,你不知道如何实现基类 类。

  2. 是的,这是有害的,但可以通过 在不使用类别 和精心选择的 属性或方法的名称,并考虑 前缀来避免。

  3. 是的,你是正确的, 限制访问你的财产。

举例#2

@interface UIView(PFXextended) 
-(NSArray*)PFXGetSubviewsOfType:(Class)class; 
@end