1

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

这是直接来自苹果类别和扩展的类扩展的解释:

@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

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

@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 会设置?
4

2 回答 2

1

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

更改类扩展或子类中的可写性是分别实现公开只读但私有可写属性和不可变类的可变子类的常见模式。Apple Objective-C Programming Guide 有一个很好的讨论

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

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

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

于 2012-11-22T17:53:51.453 回答
0

你不能retain一个float. 换个方式写吧(readonly)

MyClass对 的一无所知MyClass2,这似乎是 的子类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。如果, In MyClass2,你写

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

myFloat最终等于 4。

大概编译器不会抱怨重新定义属性 inMyClass因为这是一件非常合理的事情。这样,其他类无法写入value,但在 内MyClass,您可以写入self.value = 2;并且它会起作用。

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

于 2012-11-22T17:20:28.577 回答