好吧,你不清楚。
ruby 中的局部变量以小写字母开头(如foo、bar 或steve),并且是词法范围的(如C 变量)。它们与“类的实例”无关
ruby 中的实例变量以@ sigil 开头(如@foo、@bar 或@carl),只要self 的当前值是它们存储的对象,它们就在范围内。
如果您想要一个可以直接访问对象的实例变量的方法,则称为实例方法。比如battle_cry和initialize都是实例方法:
class Character
def initialize(name)
@name=name
end
def battle_cry
@name.upcase + "!!!"
end
def Character.default
new("Leeroy Jenkins")
end
end
相比之下,类方法是Class 对象的方法,并且不能访问该对象的任何实例变量。在上面的例子中,
default 是一个类方法。
如果您想要一个(类或实例)方法来触发当前范围的更改或从当前范围获取值,那么 ruby 使用一种称为块的回调。
class Character
ATTACKS = [ "Ho!", "Haha!", "Guard!", "Turn!", "Parry!", "Dodge!", "Spin!", "Ha", "THRUST!" ]
def attack
ATTACKS.inject(0) { |dmg, word| dmg + yield(word) }
end
end
person = Character.default
puts person.battle_cry
num_attacks = 0;
damage = person.attack do |saying|
puts saying
num_attacks += 1
rand(3)
end
puts "#{damage} points of damage done in #{num_attacks} attacks"
在上面的例子中,attack 使用 yield 关键字来调用传递的块
给它。当我们调用attack,那么,局部变量num_attacks仍然是
在我们通过它的块的范围内(这里由do ... end分隔),所以我们可以
增加它。 attack 能够将值传递到块中,在这里
它们被捕获到saying 变量中。该块还传递值
回到方法,显示为yield的返回值。
ruby 中的lambda 一词通常表示lambda 关键字,使用
使块成为独立的,功能类似于对象(它们本身通常是
称为lambdas、procs 或Procs)。
bounce = lambda { |thing| puts "I'm bouncing a #{thing}" }
bounce["ball"]
bounce["frog"]
所以我认为您要问的是您是否可以通过 Proc 代替 Hash
对于方法的参数。答案是“视情况而定”。如果只有方法
曾经使用过#[] 方法,那么是的:
class Character
attr_accessor :stats
def set_stats(stats)
@stats = stats
end
end
frank = Character.new("Victor Frankenstein")
frank.set_stats({ :str => 7, :dex => 14, :con => 9, :int => 19, :wis => 7, :cha => 11 })
monster = Character.new("Frankenstein's Monster")
monster.set_stats(lambda do |stat_name|
rand(20)
end)
但是,它可能会使用其他一些Hash 特定的方法,或者多次调用同一个键,
这会产生奇怪的结果:
monster = Character.new("Frankenstein's Monster")
monster.set_stats(lambda do |stat_name|
rand(20)
end)
monster.stats[:dex] #=> 19
monster.stats[:dex] #=> 1
在这种情况下,最好将请求缓存在中间散列中。这很容易,
因为 Hash 可以有一个初始化块。因此,如果我们将上面的内容更改为:
monster.set_stats(Hash.new do |stats_hash, stat_name|
stats_hash[stat_name] = rand(20)
end)
monster.stats[:dex] #=> 3
monster.stats[:dex] #=> 3
结果缓存在哈希中
要了解有关Hash 块初始化器的更多信息,请参阅ri Hash::new:
-------------------------------------------------------------- Hash::new
Hash.new => hash
Hash.new(obj) => aHash
Hash.new {|hash, key| block } => aHash
------------------------------------------------------------------------
Returns a new, empty hash. If this hash is subsequently accessed
by a key that doesn't correspond to a hash entry, the value
returned depends on the style of new used to create the hash. In
the first form, the access returns nil. If obj is specified, this
single object will be used for all default values. If a block is
specified, it will be called with the hash object and the key, and
should return the default value. It is the block's responsibility
to store the value in the hash if required.
h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"] #=> 100
h["c"] #=> "Go Fish"
# The following alters the single default object
h["c"].upcase! #=> "GO FISH"
h["d"] #=> "GO FISH"
h.keys #=> ["a", "b"]
# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"] #=> "Go Fish: c"
h["c"].upcase! #=> "GO FISH: C"
h["d"] #=> "Go Fish: d"
h.keys #=> ["c", "d"]