【问题标题】:Questions about Class Extensions and inheritance in objective-c关于objective-c中类扩展和继承的问题
【发布时间】:2012-11-11 02:23:43
【问题描述】:

我没有什么特别要实现的,但我正在尝试了解更多关于类扩展的信息。

这是直接来自apple Categories and extensions的类扩展的解释:

@interface MyClass : NSObject
@property (retain, readonly) float value;
@end

// Private extension, typically hidden in the main implementation file.
@interface MyClass ()
@property (retain, readwrite) float value;
@end

这对我来说确实很有意义,但是,假设我有一个 MyClass2 扩展 MyClass:

@interface MyClass2 : MyClass
@property (retain, readwrite) float value;
@end

所以我有几个问题,如果不涉及类扩展,我可以轻松回答:

  • 在运行时,当我在 MyClass 中进行赋值 self.value=2 或只是调用 float x=self.value 时,调用了哪个 setter 和 getter @property? MyClass 还是 MyClass2?
  • 编译器不应该至少发出有关重新定义只读属性的警告吗?
  • 我知道@property 有一个ivar 支持,那么到底有多少个ivar?与此相关,从 MyClass2 的角度调用相同的 self.value 哪个 ivar 会设置?

【问题讨论】:

  • 请不要将我的答案标记为正确。我最初给出了错误的答案,直到 Martin R 纠正我之后才更正它。

标签: objective-c class-extensions


【解决方案1】:

首先,属性应该是“分配”而不是“保留”,因为它们是标量类型。

更改类扩展或子类中的可写性是分别实现公开只读但私有可写的属性和不可变类的可变子类的常见模式。 Apple Objective-C 编程指南有一个good discussion

要回答您的第一个问题,只有在 MyClass 或其任何超类中声明的方法才能在 MyClass 中可见。您的私有类扩展将 setter 声明在实现的范围内,因此将被调用。 MyClass2 接口中的 readwrite 声明只是将 setter 带入公共范围。实现仍在 MyClass 中。

第二个问题的答案是否定的,不会发出警告。将可写性从只读更改为读写是有效的。

最后,只有一个 ivar。从 MyClass2 访问它会影响 MyClass 中可见的相同 ivar。

【讨论】:

  • 我没有注意到,我同意你关于标量类型的观点,但这是来自 Apple doc 的示例 :-)
  • 此时,我想知道类扩展有什么好处,如果我可以扩展一个类并将只读转换为公共。失去了保护只读属性的目的。
【解决方案2】:

你不能 retainfloat。让我们改写(readonly)

MyClassMyClass2 一无所知,它似乎是MyClass 的子类。当您编写self.value = 2 时,它将被转换为[self setValue:2],代码将从MyClass 开始并查找setValue 方法。这将被创建,因为您将value 定义为属性。 setter 方法看起来像

-(void) setValue:(int newValue) {
      _value = newValue; // _value is the actual storage for the property value
}

变量_value 将是您正在执行的对象MyClass 的实例中分配的变量。

实际上只有一个 iVar。如果,在MyClass2,你写

self.value = 3;
super.value = 4;
float myFloat = self.value;

myFloat 最终等于 4。

大概编译器不会抱怨重新定义MyClass 中的属性,因为这是一件非常合理的事情。这样,其他类不能写value,但是在MyClass内,你可以写self.value = 2;,就可以了。

我确实相信有两个 iVar,但我错了。很抱歉让任何人感到困惑。感谢 Martin R 和 BradS 对我的教育。

【讨论】:

  • 这个答案不正确。 value 属性的子类中没有第二个 ivar,并且子类没有单独的访问器函数。 anObject.value 将始终引用 MyClass 中的访问器函数,即使 anObjectMyClass2 的一个实例。
  • 但是我刚刚编译运行它,有两个!
  • 我不明白你的例子。如果您有两个不同的对象(object1 和 object2),那么每个对象当然都有自己的实例变量。
  • 在 Xcode 调试器窗口中尝试“p *object2”,您会看到 object2 只有一个 ivar(来自超类 MyClass)。
  • 抱歉,您当然是正确的。我收回我的断言。有一个 iVar。
猜你喜欢
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 2011-02-28
  • 1970-01-01
  • 2011-06-08
  • 2017-08-10
  • 1970-01-01
相关资源
最近更新 更多