关于Objective-c中的类扩展和继承的问题

时间:2012-11-22 16:35:21

标签: objective-c class-extensions

我没有特别要做的事情,而是我正在努力学习更多有关课程扩展的知识。

这是直接来自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

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

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

所以我几乎没有问题,如果不涉及课程扩展,我可以轻松回答:

  • 在运行时,在 MyClass 时,我正在执行作业 self.value = 2 或只是调用 float x = self.value ,哪个setter和getter @property被称为? MyClass或MyClass2?
  • 编译器是否应该至少发出关于重新定义readonly属性的警告?
  • 我知道@property有一个ivar支持,所以到底有多少ivar?与此相关,从 MyClass2 的角度调用相同的self.value,ivar会设置哪个?

2 个答案:

答案 0 :(得分:1)

首先,属性应该是'assign'而不是'retain',因为它们是标量类型。

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

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

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

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

答案 1 :(得分:0)

你不能retain一个float。我们改为写(readonly)

MyClassMyClass2一无所知,MyClass似乎是self.value = 2的子类。当您编写[self setValue:2]时,它将转换为setValue,代码将从MyClass开始并查找value方法。这将被创建,因为您将-(void) setValue:(int newValue) { _value = newValue; // _value is the actual storage for the property value } 定义为属性。 setter方法看起来像

_value

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

实际上只有一个iVar。如果,在self.value = 3; super.value = 4; float myFloat = self.value; 中,您可以写

myFloat

MyClass最终等于4。

据推测,编译器并没有抱怨在value中重新定义属性,因为这是非常合理的事情。这样,其他类无法写入MyClass,但在self.value = 2;内,您可以编写{{1}}并且它可以正常工作。

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