我正在尝试理解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
Run Code Online (Sandbox Code Playgroud)
现在,当我在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 (???)
Run Code Online (Sandbox Code Playgroud)
为什么#what_are_you
精致,但.preferred_accommodation
不是?
Car*_*and 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
Run Code Online (Sandbox Code Playgroud)
此外,通过将上述三个语句放在一个模块中,这两个方法的精炼版本仅限于该模块:
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
Run Code Online (Sandbox Code Playgroud)
您需要使用singleton_class范围调用优化Traveler来覆盖类方法.通过将以下代码添加到您的优化模块而不是self.included
,您可以获得预期的结果.
module Refinements
refine Traveller.singleton_class do
include Money::ClassMethods
end
end
Run Code Online (Sandbox Code Playgroud)
本文(http://timelessrepo.com/refinements-in-ruby)将帮助您更多地了解优化.