我努力在其他地方找到这个问题的另一个版本,所以如果我错过了某些内容,请道歉......我的代码片段基本上是清单5.7中的简化版本(为清晰起见)(第138页)来自David A. Black的 The Well-Grounded Rubyist(第一版),如果有人熟悉的话。
注意:我知道很少使用类实例变量,但我仍然想要理解这个例子。
作者基本上利用这种设计允许通过子类独立使用实例计数器......如果第一次调用" setter"方法(这里,在" initialize"方法中)是增量,发生了什么,拼写出来?我看到它一定是在调用" getter"方法,因为它的条件赋值按预期运行。没有它,' +'不被认为是一种方法。我只是不知道如何/为什么。发生了什么事?
类似于:@ thing_count = _________ + num
它是否正在调用" getter"空白的方法?是否有其他替代方案可以让它更清晰?
谢谢!
class Thing
def self.thing_count
@thing_count ||= 0
end
def self.thing_count=(num)
@thing_count = num
end
def initialize
self.class.thing_count += 1
end
end
first = Thing.new
second = Thing.new
third = Thing.new
puts Thing.thing_count
#=> 3
答案 0 :(得分:2)
self.class.thing_count += 1
正在调用方法def self.thing_count
,即将@thing_count
设置为0(如果尚未设置)或+ = 1(将{1}添加到如果先前已设置,则为@thing_count
)的当前值。
@thing_count ||= 0
称为memoizing,如果尚未将@thing_count
定义为任何内容,则将+
设置为0(这就是为什么+
不会是{{1}}因为它在零上呼叫{{1}}而被认可。)
答案 1 :(得分:1)
这是编写可能更容易理解的类似逻辑的一种方法:
class Thing
@@count = 0 # The double-at-sign makes this a class variable.
def initialize
@@count += 1
puts "count is now #{@@count}"
end
end
first = Thing.new
=> count is now 1
second = Thing.new
=> count is now 2
third = Thing.new
=> count is now 3
下一步是在实例外部访问类变量@@count
。为此,我们创建了访问器:
def self.count
@@count
end
def self.count=(num)
@@count = num
end
现在你可以写:
Thing.count
=> 3
您的代码基本上是同一种想法:
class Thing
def self.count
@@count ||= 0
end
def self.count=(num)
@@count = num
end
def initialize
self.class.count += 1
end
end
当您运行Thing.new
时,会发生什么事情:
initialize
self
.class
,返回Thing
类。.count
@@count
变量;如果它存在,则返回它,否则将其设置为0并返回它。+= 1
,这通常是x = x + 1
@@count
变量的值加1(但不影响@@count
变量)Thing.count=
。@@count
设为新值。代码使用这个Ruby惯用法来设置默认值。通常,对于典型的实例变量,惯用法看起来像这样:
def foo
@foo ||= "bar"
end
对于典型的类变量:
def self.foo
@@foo ||= "bar"
end
这个成语是一种懒惰的设置。在调用方法之前,该变量不存在。每次调用该方法时,它都会检查变量是否已定义(然后返回)或不是(然后设置它)。
这比设置一次效率低一点。
在我看来,将类变量显式设置为零一次是更好的编码风格,而不是使用||=
懒惰的习语。
class Demo
@@foo = "bar"
...
如果值为false,那么懒惰的设置习惯用法无法按预期工作:
def foo
@foo ||= false # This will set foo every time
end
解决方案是检查变量是否已定义:
def foo
defined?(@foo) ? @foo : (@foo = false)
end
另一个Ruby习惯用法是将方法和变量命名为同名。这就是Ruby执行attr_reader
,attr_writer
和attr_accessor
的方式。
对于您的代码,请注意您没有任何attr_
代码,因此如果您愿意,可以使用您想要的任何变量名称,例如:
def self.count
@@whatever ||= 0
end
def self.count=(num)
@@whatever = num
end
这对于信息隐藏目的非常有用。
评论者allielarson1212
提出了一个很好的观点,即成语有时被称为“记忆”。 “备忘录”成语通常更像是这样:
def foo
@foo ||= ... a long time-consuming command ...
end
这是做什么的: