这里有一个小问题,变量没有初始化。这些是等价的吗?
comments
^ comments ifNil: [ comments := OrderedCollection new ]
-
comments
^ comments ifNil: [ self initializeComments ]
initializeComments
comments := OrderedCollection new
答案 0 :(得分:2)
让我试着建立这个问题。
延迟初始化
这种技术在节省时间和/或记忆时是有意义的。如果要初始化的对象很大,或者初始化它需要的时间太长,那肯定是有道理的。否则,它没有。
在做出决定时,请考虑以下因素:
时间:对ivar的每次访问都将执行条件语句(ifNil:
)。因此,您必须决定在开始时初始化ivar是否更好,然后只需使用它而无需进一步检查。
空间:对象需要一些字节,当然。但是#initializeFoo
方法也需要一些字节,因为它是CompiledMethod
。例如,如果你写
initialize
comments ifNil: [self initializeComments].
^comments
而不是
initialize
^comments ifNil: [comments := OrderedCollection new]
您必须将OrderedCollection
的新实例使用的空间与由CompiledMethod
对象定义的空间进行比较:
initializeComments
comments := OrderedCollection new
加上#comments
访问者方法中的发送。
此外,惰性初始化技术可防止对ivar的任何直接引用。例如,如果comments
是惰性的,则代码将被强制在任何地方使用self comments
,BTW会占用额外的空间,因为发送方需要在{{1}的文字框架中使用一个插槽选择器。许多人认为无论如何都应该通过消息访问ivars,但是没有选择仅仅命名ivar也不是一件好事。此外,访问ivar两次的方法,通常最终发送两次getter消息,或者第一次发送它(并且以相同的方法)直接访问ivar(这也不是一个好主意)。例如,
#comments
在这两种情况下,第一行都会发送消息以确保ivar已初始化。第二行有两个选项:它再次发送消息(这是不必要的)或使用ivar,因为程序员知道上面已经初始化了ivar。第二种选择容易出错。例如,存在以下错误的风险:
addComment: aString
(self comments includes: aString) ifTrue: [^self].
self comments add: aString
addComment: aString
(self comments includes: aString) ifTrue: [^self].
comments add: aString
在决定早期与懒惰初始化时,我也会考虑第三种选择。例如,可以在另一个方法中内联初始化。例如,考虑
addComment: aString
(self acceptsDuplications not and: [self comments includes: aString])
ifTrue: [^self].
comments add: aString
如果没有必要,不需要初始化ivar。
延迟初始化还有另一个副作用。例如,假设客户说
commentsDo: aBlock
comments isNil ifTrue: [^self].
comments do: [:c | aBlock value: c]
其中 <receiver> comments isEmpty ifTrue: [^self nothingToDo].
是拥有<receiver>
ivar的对象。此客户端代码可能会产生无意义初始化ivar的副作用。当然,客户不应该这样做。相反,comments
应该实现<receiver>
服务,但这些是在使用LI技术填充代码之前要考虑的事项。
答案 1 :(得分:1)
必须在comments
方法中返回initializeComments
变量,否则comments
getter方法将在未初始化变量的情况下为第二个变量返回self
。
我不想在initializeComments
中返回任何内容,所以我使用了:
comments
^ comments ifNil: [ self initializeComments. comments ]
或者:
comments
comments ifNil: [ self initializeComments ].
^ comments
谢谢Mike!
<强> PS。有关更详细的说明,请参阅下面的@LeandroCaniglia答案。