我试图了解Ruby的优化功能,而且我遇到了一个我不理解的场景。
以此示例代码:
class Traveller
def what_are_you
puts "I'm a Backpacker"
end
def self.preferred_accommodation
puts "Hostels"
end
end
module Refinements
module Money
def what_are_you
puts "I'm a cashed-up hedonist!"
end
module ClassMethods
def preferred_accommodation
puts "Expensive Hotels"
end
end
def self.included(base)
base.extend ClassMethods
end
end
refine Traveller do
include Money
end
end
现在,当我在REPL中执行此操作时:
Traveller.new.what_are_you # => I'm a Backpacker
Traveller.preferred_accommodation # => Hostels
using Refinements
Traveller.new.what_are_you # => I'm a cashed-up hedonist!
Traveller.preferred_accommodation # => Hostels (???)
为什么#what_are_you
被提炼,但.preferred_accommodation
不是?
答案 0 :(得分:16)
正如@MasashiMiyazaki解释的那样,你必须改进两个类:Traveller
和Traveller
的单例类。这实际上可以让你简化代码:
module Money
refine Traveller do
def what_are_you
puts "I'm a cashed-up hedonist!"
end
end
refine Traveller.singleton_class do
def preferred_accommodation
puts "Expensive Hotels"
end
end
end
Traveller.new.what_are_you #=> I'm a Backpacker
Traveller.preferred_accommodation #=> Hostels
using Money
Traveller.new.what_are_you #=> I'm a cashed-up hedonist!
Traveller.preferred_accommodation #=> Expensive Hotels
此外,通过将上述三个语句放在一个模块中,这两个方法的精炼版本仅限于该模块:
module M
using Money
Traveller.new.what_are_you #=> I'm a cashed-up hedonist!
Traveller.preferred_accommodation #=> Expensive Hotels
end
Traveller.new.what_are_you #=> I'm a Backpacker
Traveller.preferred_accommodation #=> Hostels
答案 1 :(得分:5)
您需要使用singleton_class范围调用优化者Traveler来覆盖类方法。通过将以下代码添加到您的优化模块而不是self.included
,您可以获得预期的结果。
module Refinements
refine Traveller.singleton_class do
include Money::ClassMethods
end
end
这篇文章(http://timelessrepo.com/refinements-in-ruby)将帮助您更多地了解优化。