在 Objective-C 中将私有可变属性隐藏在不可变接口后面

Hiding privately mutable properties behind immutable interfaces in Objective-C

提问人:Lukas Kalinski 提问时间:9/17/2013 最后编辑:Lukas Kalinski 更新时间:1/9/2017 访问量:1414

问:

所以,我基本上想问的是以下代码是否安全(而不是它是否有效,因为它确实如此)。即,public getter 是否会覆盖 actionLog 属性 [属于不同类型] 的合成 getter?

.h 文件:

@interface SomeClass : NSObject
- (NSArray*) actionLog;
@end

.m 文件:

@interface SomeClass ()
@property (strong, nonatomic) NSMutableArray* actionLog;
@end

@implementation SomeClass
...
@end
目标-C 性能 不变性 可变

评论


答:

5赞 bbum 9/17/2013 #1

这不仅没问题,而且正是当初创建类扩展的原因!

是的,将按预期生成单个自动合成的 ivar 和一对 getter/setter 方法。


对不起 -- 错过了比赛。 部分。不,你不能那样做;类型必须相同。NSArrayNSMutableArray

但是,您无论如何都不想返回可变数组。首先,调用方可能会修改它(错误)。但是,更重要的是,调用方将假设内容是 API 所暗示的不可变的),因此,当该数组的内容从调用方下方更改时,可能会导致问题(例如;调用方可以合理地假设结果将是稳定的并且可以缓存)。count

评论

1赞 Lukas Kalinski 9/17/2013
特别感谢您对拥有类别的最初原因的宝贵见解!
0赞 Lukas Kalinski 10/24/2013
我现在的经验是,在公共接口中使用 NSArray* 而在私有接口中使用 NSMutableArray* 似乎不起作用。您是否注意到我的代码中的这种差异,或者您只是回答了 readonly 属性标签的使用?
0赞 Lukas Kalinski 10/25/2013
我没有考虑过“向不可变对象发送变异消息”的问题。非常感谢您的见解!只是为了澄清;我假设我应该做的是在“- (NSArray*) actionLog”方法中返回数组的副本。还有一件事,我现在看到我在上面的代码中有 readonly actionLog 属性;这是错误的,我现在将编辑它,我只想在公共界面中拥有显式的 getter。
1赞 malhal 1/9/2017 #2

通过使用可变 ivar 支持属性,如下所示:

.h 文件:

@interface SomeClass : NSObject

@property (nonatomic, strong) NSArray *actionLog;

@end

.m 文件:

@implementation SomeClass{
    NSMutableArray* _actionLog;
}

-(void)insertAction:(Action *)action{
    if(!_actionLog){
        _actionLog = [[NSMutableArray alloc] init];
    }
    [_actionLog addObject:action];
}

@end