18

在几种情况下,您可能会覆盖超类的属性。

  1. 您声明一个与其超类具有相同名称和相同属性的属性。(因为如果您更改属性,您会收到编译器警告)。您可以使用您创建的 ivar 进行综合。这有什么用?或者它有什么害处?

  2. 如果超类在类扩展(没有名称的类别)中声明了一个属性,那么它可能不在头文件中。如果您不知道头文件中的该属性,则可以使用您想要的任何属性或类声明同名属性。但是 setter/getter 方法将覆盖那些“秘密属性”。我认为这只会造成伤害。但是既然从头文件中不知道,那怎么避免呢?

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

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

4

2 回答 2

5

你提到的每种情况都有一个合适的地方,在野外使用的频率不同。你只需要小心不要踩到自己。我将用我个人遇到的例子来说明。

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

私有财产
这比你想象的更有用。私有财产的替代品是普通的 ol' ivar,我们都熟悉。如果这是一个以某种频率变化的 ivar,那么您最终会得到如下所示的代码块:

[_myIvar release], _myIvar = nil;

或者:

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

虽然看起来还不错,但像这样的内存管理样板代码变得非常陈旧,非常快。或者,我们可以将上面的示例实现为具有保留语义的私有属性。这意味着,无论如何,我们只需要:

self.myIvar = someValue;

一段时间后,这对眼睛和手指来说要容易得多。您注意到这一点是正确的,因为这个属性对宇宙的其他部分是不可见的,它可能会意外地被子类覆盖。这是在 Objective-C 中开发时的固有风险,但您可以采取措施使风险变得非常小。这些措施是以可预测的方式修改您的私有财产名称的变体。您可以在这里采取无限的道路:例如,您将私人财产名称前加上您的姓名首字母和下划线作为个人政策。对我来说,我会得到类似mw_ivar, 和相应-setMW_ivar:-mw_ivar访问器。是的,从统计上讲,有人可能会出现并意外覆盖该名称,但实际上,他们不会。特别是如果您有办法将您的实践发布给可能使用您的代码的人。而且,我可以肯定地说,Apple 并没有四处走动并制造以这种方式破坏的私有财产,因此您在这方面也很安全。

Publicly Readonly, Private Readwrite
这只是标准做法。你是对的,它很有用,而且它并不危险,因为属性在标题中。任何不小心超越它的人都只能怪自己。

于 2011-04-13T17:07:38.450 回答
0

好问题

  1. 使用它是您作为开发人员应该知道您此时正在做什么并且需要向基类属性添加自定义。并且由于您知道自己在做什么,super除非您有充分的理由不这样做,否则您将正确地调用 s 实现。不调用 super 的决定可能是有害的,尤其是在您不知道如何实现基类的情况下。

  2. 是的,这是有害的,但可以避免过度使用类别并仔细选择属性或方法的名称并考虑为其添加前缀。

  3. 是的,您是正确的,这有利于限制对您的财产的访问。

#2 的示例

@interface UIView(PFXextended)
-(NSArray*)PFXGetSubviewsOfType:(Class)class;
@end
于 2011-04-13T14:52:10.167 回答