class Numeric
@@currencies = {'dollar' => 1, 'yen' => 0.013, 'euro' => 1.292, 'rupee' => 0.019}
attr_writer :previous_currency
def method_missing(method_id)
singular_currency = method_id.to_s.gsub( /s$/, '')
if @@currencies.has_key?(singular_currency)
@previous_currency = singular_currency
self * @@currencies[singular_currency]
else
super
end
end
def in(currency)
singular_currency = currency.to_s.gsub( /s$/, '')
rate = @@currencies[singular_currency]
if @@currencies[@previous_currency] < rate
self / rate
else
self * rate
end
end
end
Numeric类的扩展允许执行以下操作:
<Number>.<currency>.in(:<other_currency>)
喜欢5.dollars.in(:euros)
如果我有dollars
作为我的第一个缺失方法,它就可以了。 @previous_currency
在第一次拍摄时获得值dollar
,然后在调用缺失的方法in
时,它会保留其值并完成转换。但是,如果我尝试其他任何内容而不是dollars
或dollar
,@previous_currency
会以某种方式失去其价值,在nil
的调用下再次成为in
,从而导致跟随错误
NoMethodError: undefined method ` for nil:NilClass
我试图在@@currencies
哈希中切换美元的位置,但同样的行为再次发生。
Ruby是否更喜欢美元?
答案 0 :(得分:1)
问题是你试图在一个数字上保持状态,然后返回一些完全不同的数字。
使用美元,5.dollars
会返回5
,因为您天真地认为“1”的确意味着“1美元”,(那么为什么即使使用1.dollar
也是如此1.in(:euros)
?),因此5的@previous_currency
dollar
。 5.dollars
会返回同一个对象,5
,并附加您附加的额外状态。
使用euros
,5.euros
会返回6.46
,这是一个完全不同的对象。它与对象5
不共享任何状态,因此尚未设置@previous_currency
。
为了完成这项工作,您需要停止维护状态,并始终以美元返回结果,方式与5.weeks
,5.months
和{{ 1}}返回几秒钟。然后你有一个简单的无状态数字。您还应该停止依赖5.years
,并动态定义方法。这是一个简单的工作版本:
method_missing