在ObjC类别中声明属性是否会覆盖在公共接口上声明的同名属性?

时间:2019-02-05 23:15:55

标签: objective-c

这并不是要解决任何特定的问题,只是希望了解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')

这使我认为这是一个完整的重新声明,但是现在我不太确定实际发生了什么。寻找澄清。

2 个答案:

答案 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,则将完全不会生成设置器。

您的各种警告实际上说明了我们正在处理同一个属性,因为这只是示例,您的重新声明的性质与公共接口中包含的内容不兼容。