我正在尝试使用method_missing将美元转换为不同的货币。
class Numeric
@@currency={"euro"=>2, "yen"=>6}
def method_missing(method_id,*args,&block)
method_id.to_s.gsub!(/s$/,'') #get rid of s in order to handle "euros"
@@currency.has_key?(method_id) ? self*@@currency[method_id] : super
end
end
> 3.euro #expect to return 6
NoMethodError: undefined method 'euro' for 3:Fixnum
from (pry):24:in 'method_missing'
> 3.euros #expect to return 6
NoMethodError: undefined method 'euros' for 3:Fixnum
from (pry):24:in 'method_missing'
我猜3.euro
无效,因为:euro.to_s.gsub!(/s$/,'')
会返回nil
。我不确定为什么它不会返回方法错误。
感谢您的帮助。
答案 0 :(得分:4)
当 method_missing 被调用时,euro
将作为符号分配给method_id
。但是,您的@@currency
哈希将所有键都保存为字符串,您需要将它们转换为符号。
method_id.to_s.gsub!(/s$/,'')
无法改变实际对象method_id
。由于method_id.to_s
会为您提供一个新的字符串对象,因此#gsub!
仅对此有用。你无法改变method_id
,它仍然保持原样。最好使用 non-bang ,因为如果没有做出更改,它将为您提供实际对象,或者如果进行了更改,则会更改对象,那么您需要将此返回值分配给新变量。
通过@@currency
,@@currency.has_key?(method_id)
评估为false
,super
类method_missing
已被调用。为什么?由于method_id
未转换为字符串,您可能会发生这种情况。
但是,如果你想回复euro
或euros
,那么
class Numeric
@@currency={"euro" => 2, "yen" => 6}
def method_missing(method_id,*args,&block)
#get rid of s in order to handle "euros"
new_method_id = method_id.to_s.gsub(/s$/,'')
@@currency.has_key?(new_method_id) ? self*@@currency[new_method_id] : super
end
end
3.euros # => 6
3.euro # => 6
答案 1 :(得分:1)
gsub!
修改字符串并返回nil
。对于您正在使用的字符串,它不会很好地工作,这是to_s
创建的临时字符串,并且永远不会存储在变量中。此外,您甚至无法将结果存储在任何地方。为什么字符串上的gsub!
应该修改符号,这些符号无论如何都是不可变的?
尝试使用gsub
代替,它返回修改后的字符串并让调用者独自离开。您还需要存储返回值。
real_method_name = method_id.to_s.gsub(/s$/, "")
另外:3.euro
无效的原因是因为您的哈希使用字符串作为键,但method_id
作为符号传递给方法。如果您不必进行字符串操作(在这种情况下删除s后缀),我建议只使用符号作为您的哈希键。但实际上,你需要进行字符串操作,所以我的答案是使用字符串。