覆盖 getter 只需要 @synthesize
Posted
技术标签:
【中文标题】覆盖 getter 只需要 @synthesize【英文标题】:override getter only needs @synthesize 【发布时间】:2013-12-11 15:07:36 【问题描述】:我想为惰性实例化覆盖 getter 并保留默认设置器。
我需要@synthesize 吗?
为什么?
@interface Foo()
@property (strong, nonatomic) NSObject *bar;
@end
@implementation Foo
- (NSObject *)bar
if(!_bar) _bar = [[NSObject alloc] init];
return _bar;
@end
更新:我更改了变量和类名,因为它令人困惑。从 Deck 和 card 到 Foo 和 bar。
【问题讨论】:
你开发什么?即ios6
,iOS7
等因为理论上我认为它来自iOS6
,当使用ARC
时你不需要@synthesize
忘记@synthesize
iOS7.当您同时覆盖 setter 和 getter 时,您需要 @synthesize。这个例子来自斯坦福:开发 iOS7,第 2 讲
【参考方案1】:
不,如果您显式实现所有访问器方法(readwrite
属性的 getter 和 setter,readonly
属性的 getter),您只需要显式合成(以获取合成的 ivar)。您已经为此readwrite
属性编写了getter,但没有编写setter,因此仍会为您合成ivar。因此,就您的代码而言,您不需要显式地@synthesize
。
如果你创建了这个属性readonly
,那么实现一个getter 会阻止你的ivar 被自动合成。同样,由于这是readwrite
,如果您同时实现了getter 和setter,则需要您合成ivar(如果您想要的话)。
【讨论】:
+1 换句话说:如果你的代码可以编译,你就很好。如果您需要@synthesize
,编译器将不允许您使用_cards
ivar。【参考方案2】:
不要以这种方式使用延迟初始化。没有卡片的 Deck 是无用的,因此,每当第一次调用该 getter 时,延迟初始化只会给您带来不确定的 CPU 消耗。幸运的是,简单地创建一个可变数组没有任何成本(这也是不使用延迟初始化的原因)。
同样,出售可变集合会破坏封装。一个套牌应该包含所有逻辑,以确定它包含哪些卡片以及按什么顺序。通过出售可变集合,外部代码可以在 Deck 背后改变该顺序。
除此之外,“设置”一副牌的牌意味着什么?走这条路似乎将所有与维护 Deck 相关的逻辑推到了 Deck 类之外,提出了一个问题,即为什么甲板只不过是任何使用甲板的类中的普通旧数组。
【讨论】:
您的某些观点并不完全有效。正如您所说,性能无关紧要。可变属性的惰性吸气剂将确保它不能被取消。例如self.cards = nil; [self.cards addObject:card];
完美运行。
@iMartin 不能“完美地工作”,除非任意丢失状态是可以的。改变状态的 getter,即使是延迟初始化,都是糟糕的设计,随着时间的推移会导致严重的问题。最好有一个 resetState
方法,它实际上按照它所说的那样做。
@iMartin 为什么要将属性公开为readwrite
?这样的属性应该是readonly
和setCards:
会引发编译器错误。这里的一切听起来都像是糟糕的设计。
你们把很多事情搞砸了。我没有说任何关于暴露可变集合的事情。这当然是糟糕的设计。你注意到self
了吗?我说的是在类 inside 中使用该集合。在任何地方,您都可以不小心将nil
分配到那里,之后就不会发生任何突变。这是最常用的情况之一,我使用延迟初始化。它工作完美。然后是readonly
的事情。设置卡组有什么问题?很正常,为什么要在这里提?
防御“意外分配 nil”有点浪费。 “哎呀,我不小心分配了 nil 并且丢失了所有游戏状态的集合。但是,不用担心,下次我调用 getter 时,我会返回一个空游戏状态或默认顺序的游戏状态。当然,用户永远不会注意到!” 变异的 getter 是糟糕的设计,延迟初始化通常不建议使用。【参考方案3】:
在 iOS 7 中,您通常不需要合成。如果你想要一个自定义的 getter,只需定义一个。您将免费获得默认设置器。
【讨论】:
合成与iOS7无关。 @LeoNatan:据我记得,你在 ios5 中确实必须@synthesize
,对吧?
它与 xcode 和 LLVM 版本有关 - 对于 Xcode 4.4 和 LLVM Compiler 4.0,不再需要 @synthesize
指令,因为它将默认提供以上是关于覆盖 getter 只需要 @synthesize的主要内容,如果未能解决你的问题,请参考以下文章