宣称的私人ivars与合成的ivars有何不同?

lem*_*nar 1 objective-c

我知道现代的Objective-C运行时可以合成ivars.我认为合成的ivars的行为与标记的ivars完全相同@private,但它们没有.

因此,代码仅在我预期可以处理的现代运行时下进行编译.例如,一个超类:

@interface A : NSObject {
#if !__OBJC2__
  @private
    NSString *_c;
#endif
}

@property (nonatomic, copy) NSString *d;

@end


@implementation A

@synthesize d=_c;

- (void)dealloc {
    [_c release];
    [super dealloc];
}

@end
Run Code Online (Sandbox Code Playgroud)

和子类:

@interface B : A {
#if !__OBJC2__
@private
    NSString *_c;
#endif
}

@property (nonatomic, copy) NSString *e;

@end


@implementation B

@synthesize e=_c;

- (void)dealloc {
    [_c release];
    [super dealloc];
}

@end
Run Code Online (Sandbox Code Playgroud)

即使超类的ivar是私有的,子类也不能具有与其超类的声明的ivar同名的声明的ivar.这似乎违反了我的意思@private,因为子类受到超类选择私有的影响.

然而,我更关心的是我应该如何看待合成的伊娃.我认为他们的行为就像宣布的私人伊娃,但没有脆弱的基类问题.也许这是正确的,我只是不明白脆弱的基类问题.为什么上面的代码只在现代运行时编译?当所有超类实例变量都是私有的时,是否存在脆弱的基类问题?

Mat*_*her 6

合成的伊娃私人的.你所看到的是编译器正常工作.

忽略!__OBJ2__条件内的代码.我只会看一下合成的ivars案例.

这就是您的代码所具有的:

  • A::_c是一种合成的ivar,只能在实施过程中访问A.
  • B::_c是一种合成的ivar,只能在实施过程中访问B.

它们不是同一个变量.它们不会发生冲突,也不会存储相同的值.

仍然可能出现问题的情况......

如果您尝试将Aand和B实现放在同一个文件中,编译器现在可以A::_c在编译B时查看声明,并阻止您_c在该@synthesize e=_c;行中访问B.

它为什么要这样做?我不是只是这么说A::_c而且B::_c是不相关的变量吗?

将两个实现放在同一个文件中会产生一种情况,_c即编译器到达时不是未声明的标识符@synthesize e=_c;,因此编译器不会尝试创建新的合成ivar B,而是尝试访问A::_c并失败(因为它A::_c是私有的).