我有以下Ticket类:
class Ticket
VALID_STATES = %i[open closed invalid wontfix]
attr_reader :status
def status= new_state
new_state = new_state.to_sym
@status = new_state
end
end
当传递String而不是Symbol时,即使getter方法返回了正确的值,setter方法也会意外地返回一个String。例如:
t = Ticket.new
t.status = 'closed'
#=> "closed"
t.status
#=> :closed
看起来正确的值是存储作为一个符号,但我不知道为什么当最后一个表达式评估时该方法在REPL返回"closed"
的原因应该返回:closed
。我的期望是,有问题的表达式应该解析为@status = :closed
,因此应该返回一个符号。
有人可以解释为什么我从字符串而不是符号作为setter方法的返回值吗?
@status = new_state.to_sym
而不是分配回 new_state ,但是有一些中间代码被删除以创建这个最小的例子。我不想过多地更改代码,因为这样就无法显示我的真实代码在做什么。无论如何,它似乎对这个特定问题没有任何影响;我已经尝试过两种方式。def foo=(str); @foo = str.to_sym; end
之类的替代抽象进行调试会进一步导致兔子洞。答案 0 :(得分:5)
预计。来自documentation:
请注意,对于赋值方法,返回值始终为 忽略。相反,将返回参数:
def a=(value) return 1 + value end p(a = 5) # prints 5
Ruby允许你链接作业:
foo = bar = 'closed'
上述内容为"closed"
和foo
分配了bar
。
返回参数并忽略方法的返回值,可以用方法调用替换bar
:
foo = t.status = 'closed'
如果以上情况将:closed
分配给foo
,IMO会感到非常惊讶。
如果您真的想要返回值,请使用send
或public_send
:
def a=(value)
return 1 + value
end
p(a = 5) # prints 5
p(send(:a=, 5)) # prints 6
答案 1 :(得分:1)
答案很简单:在Ruby中,赋值评估为赋值。方法分配没有什么特别之处。