【问题标题】:Inherited properties and synthesizing in Objective-CObjective-C 中的继承属性和综合
【发布时间】:2012-09-23 21:15:59
【问题描述】:

我有以下类和子类:

@interface NSHigh : NSObject
@property (nonatomic, strong) NSArray *array;
@end
@implementation NSHigh
-(NSArray*)array
{
    _array = [[NSArray alloc] init];
    return _array;
}
@end

@interface NSLow : NSHigh
@end
@implementation NSLow
/* synthesizing makes the assertion FAIL. NO synthesizing makes the assertion PASS */
@synthesize array;
@end

然后我在某处运行这段代码:

NSLow *low = [[NSLow alloc] init];
assert(low.array);

所以,显然,如果我在子类NSLow 中合成了数组属性,那么来自超类的getter 不会被调用,并且断言失败。

如果我不合成,则调用超类getter,断言通过。

  1. 为什么会这样?
  2. 如何在不每次调用self.array 的情况下访问NSLow 子类中的数组实例变量?

【问题讨论】:

  • 不要在你的类名前加上NS。这是 Apple 保留的。
  • @JonathanGrynspan 这是一种预防措施,还是苹果也会拒绝该申请?
  • 称之为语言要求。
  • 对于那些感兴趣的人来说,NS 代表 Cocoa 框架最初来自的 NeXTSTEP:stackoverflow.com/a/473866/159758

标签: objective-c ios inheritance


【解决方案1】:

NSLow 中的@synthesize 将创建以下 getter:

- (NSArray *)array {
    return _array;
}

因此,您的数组永远不会被初始化,并且会返回 nil

您通常不应将@synthesize 用于在超类中声明的@properties

另外,您不应该实现像NSHigh 中的getter。如果你想懒惰地初始化那个数组,你应该这样做:

- (NSArray *)array {
    if (!_array) {
        _array = [[NSArray alloc] init];
    }
    return _array;
}

最后,你不应该使用NS 前缀。

编辑:

如果你想在子类中直接访问你的 ivar,你可以像这样在头文件中显式声明它:

@interface NSHigh : NSObject {
    NSArray *_array;
}
@property (nonatomic, strong) NSArray *array;
@end

这也将允许您访问子类中的 ivar。

【讨论】:

  • 所以我必须从所有子类中显式调用 self.property 吗?没有其他办法解决这个问题吗?这是什么原因?
  • 但是如果你真的想要直接访问,你可以在超类接口中显式声明你的ivar。
  • @DrummerB 合成的吸气剂会使用_array ivar吗?也就是带下划线前缀?
  • 其实不,你是对的。如果您只是调用@synthesize array;,如果将使用名为array 的ivar。如果让它自动合成,它将使用_array。或者您也可以使用@synthesize array = _array; 使其在显式合成时使用_array
  • if (_array) ...不应该是if (!_array) ...吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 2012-04-19
  • 2012-01-05
相关资源
最近更新 更多