这并不是要解决任何特定的问题,只是希望了解Objc中属性的细微差别。
说我有一个课程Dude
# Dude.h
@interface Dude: NSObject
@property (readonly, nonatomic) NSNumber *height;
@end
我在实现文件中扩展了类,但是更改了属性。
# Dude.m
@interface Dude()
@property (readwrite, atomic) NSNumber *height;
@end
@implementation Dude
@end
我得到一个错误。
属性“高度”上的“ atomic”属性与该属性不匹配 继承自“ Dude”
那么这里到底发生了什么。扩展名上的属性是否相同?我是在重写访问器吗?
另外,当我更改顺序以使公用接口为readwrite
而专用接口为readonly
时,也会出现错误:
在类扩展名'Dude'中非法声明属性(属性 必须为'readwrite',而其主目录必须为'readonly')
这使我认为这是一个完整的重新声明,但是现在我不太确定实际发生了什么。寻找澄清。
答案 0 :(得分:3)
您可以将其更像是公共和私有界面。
.h文件中声明的接口是您的类的公共接口。 因此,如果您有理由将属性声明为只读,那么在那里有意义。
.m文件中的无名类别(Dude())是您对属性的私人印象。因此,您可以在此处指定readwrite,以使您的类能够在内部更改属性,但不能在外部更改。
您还可以将这些声明用于方法,以在.h中声明公共接口,并在.m中声明接口Dude()的私有方法。
您的公共接口和私有接口中的组合必须合理,您不能声明公共属性为readwrite并在内部说它只是只读的...
最后是Objective-C:这仅适用于您的编辑器和编译器。即使存在的一切都被声明为某种私有,也可以对其进行访问。
答案 1 :(得分:1)
在Apple的The Objective-C Programming Language中,他们以属性的重新声明为例,对“扩展名”进行了如下描述:
扩展名
类扩展类似于匿名类,除了它们声明的方法必须在相应类的主
@implementation
块中实现。使用Clang / LLVM 2.0编译器,您还可以在类扩展中声明属性和实例变量。类扩展的常见用法是重新声明被公开声明为只读的属性,并将其私有地声明为readwrite:
@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
...
因此,如此处所示,此模式用于“重新声明”属性。不过,它是同一个属性。即使要将公共接口声明为readonly
,也只有在希望编译器合成私有设置程序时才重新声明属性。如果您未在扩展程序中将属性重新声明为readwrite
,则将完全不会生成设置器。
您的各种警告实际上说明了我们正在处理同一个属性,因为这只是示例,您的重新声明的性质与公共接口中包含的内容不兼容。