Хорошо, вы не поняли.
Локальные переменные в рубине начинаются со строчной буквы (например, foo
, bar
или steve
), и лексическую область видимости (как C
переменные). Они не имеют ничего общего с «экземпляром класса»
Переменные в рубине начинаются с @
сигилы (как @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
.
слово lambda
в рубина, как правило, означает lambda
ключевое слово, которое используется, чтобы сделать блоки в автономных, функции, как объекты (которые сами по себе, как правило, упоминаются как lambda
с, proc
с, или Proc
с).
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"]
Вы можете уточнить - это ли lamdba время вызываемый код has_attached_file и, следовательно, из ваших рук? Потому что вы можете передавать параметры в lamdbas, когда вы их называете, и можете передавать «я» так же легко, как и все остальное. – Matt