Странное поведение ruby attr_accessor
У меня есть этот блок кода:
class CallMe
attr_accessor :a, :b, :c
def self.start(*args)
self.new(*args).get_answer
end
def initialize(a,b,c)
@a = a
@b = b
@c = c
end
def get_answer
if c
b = nil
else
return b
end
end
end
answer = CallMe.start(1,2,nil)
Почему, когда я запускаю его в IRB, я всегда получаю answer = nil
четный логический случай - получить значение b, равное 2
2 ответа
Переменный эффект Подъем используется во многих языках. Для Ruby это описано в официальной документации:
Локальная переменная создается, когда синтаксический анализатор встречает назначение, а не когда происходит назначение
Так, get_answer
метод создает локальную переменную b
независимо от стоимости c
, И назначает локальную переменную b
в nil
при создании. затем get_answer
возвращает локальную переменную b
который всегда nil
,
Правильный метод:
def get_answer
c ? self.b = nil : b
end
Это потому, что в контексте if
заявление, которое вы на самом деле переопределить b
когда вы печатаете b = nil
, Для Ruby не ясно, хотите ли вы вызвать метод объекта :b
или создать новую переменную b
, В таких случаях приоритет всегда переходит от глобального к ближайшему контексту, в данном случае - к контексту внутри if
блок.
Если вы измените
if c
b = nil
else
return b
end
# to
if c
# b = nil
# or
self.b = nil
else
return b
Вы заметите, что это работает, как вы ожидали.