继承属性时,在readon从readonly读取继承属性时未设置合并器

时间:2013-06-19 17:58:16

标签: ios objective-c cocoa inheritance

我在使用属性时发现了一种奇怪的行为,它继承为readonly而不是在继承的类中重新声明为readwrite

A.h

@interface A : NSObject

@property (nonatomic, strong, readonly) NSObject * someProperty;

@end

B.h

@interface B : A

// no matter if here
// @property (nonatomic, strong, readwrite) NSObject * someProperty;

- (void)foo;

@end

B.m

@interface B()

// no matter if here
@property (nonatomic, strong, readwrite) NSObject * someProperty;

@end

@implementation B

- (void)foo {

    NSLog(@"%@", self.someProperty);

    // crash here with unrecognized selector setSomeProperty:
    self.someProperty = [NSObject new];
}

@end

致电

self.someProperty = [NSObject new];

导致代码在无法识别的选择器“setSomeProperty:”上崩溃

调查显示,即使宣布为readwrite,看起来setter也没有得到合成

为什么会这样?编译器没有表明发生这种情况的任何警告,也没有发现任何记录此行为的地方

2 个答案:

答案 0 :(得分:2)

向B.m文件添加@synthesize指令,崩溃将消失:

@synthesize someProperty = _someProperty;

问题在于,在父类中,您将属性声明为readonly,因此没有为其合成的setter。子类继承了这种行为。即使您将属性重新声明为子类中的readwrite@synthesize命令将指示编译器再次为类B生成访问器方法。

希望这有帮助!

enter image description here

答案 1 :(得分:2)

我不能给你一个官方参考,但这是我所经历的:对于从超类继承的属性,编译器不会生成任何访问器方法。< / p>

在您的情况下,该属性在A类中声明为readonly,以便编译器创建 只有一个getter方法。 B类中的重新声明不会创建任何其他访问者 方法。原因可能是B类不知道在A类中如何实现属性(它不必是实例变量)。

因此子类中的属性声明只是对编译器的“承诺” getter和setter函数将在运行时可用(类似于@dynamic声明)。 如果没有setter,那么你将获得运行时异常。

因此,在子类中重新声明属性的用例将是超类 在 public 接口中将该属性声明为只读,但在。中以读写方式声明 (私人)类扩展名:

// A.h
@interface A : NSObject
@property (nonatomic, strong, readonly) NSObject * someProperty;
@end

// A.m
@interface A()
@property (nonatomic, strong, readwrite) NSObject * someProperty;
@end

@implementation A
@end

在这种情况下,setter和getter都是在A类和B类中创建的 可以在其实现中将该属性重新声明为读写。