通过The Ruby programming language阅读后,我找到了使用alias
关键字来扩充方法的示例。
def hello # A nice simple method
puts 'Hello world' # Suppose we want to augment it...
end
alias original_hello hello # Give the method a backup name
def hello # Now we define a new method with the old name
puts "Your attention please" # That does some stuff
original_hello # Then calls the original method
puts "This has been a test" # Then does some more stuff
end
确实original hello
保留旧行为,即使重新定义了它所引用的方法之后也是如此。
但是,在我看来,这个例子几乎没有说明这种技术的真正好处。不能以传统的方式实现(例如通过提供块)?那为什么要用这个成语呢?当使用alias
进行扩充真的有意义时,任何人都可以提供来自现实世界的示例吗?
答案 0 :(得分:5)
Rails代码充满了这些。想象一下原始hello
方法不属于您的代码库。在第三方库的某处,在类do_stuff(stuff)
上声明了Stuffer
方法。
你想要例如调试这个方法。你重新打开这个类,定义一个别名,然后瞧瞧:
class Stuffer
alias original_do_stuff do_stuff
def do_stuff(stuff)
puts stuff.inspect
original_do_stuff(stuff)
end
end
现在所有代码,包括您可能甚至不知道的原始第三方代码,都会打印出传递给do_stuff
每次调用的参数。
现实生活中的例子(不要在家里和学校里试试这个:)
class String
alias _inspect inspect
def inspect
puts "I am a string: “#{_inspect}”"
end
end
"abc".inspect
#⇒ I am a string: “"abc"”
答案 1 :(得分:4)
当使用
alias
进行扩充真的有意义时,任何人都能提供来自现实世界的示例吗?
不是真的。今天,你会这样做(例如取自@mudasobwa's answer):
module WeirdInspectRefinement module WeirdInspectExtension def inspect "I am a string: “#{super}”" end end refine String do prepend WeirdInspectExtension end end using WeirdInspectRefinement p 'abc'.inspect #⇒ 'I am a string: “"abc"”'
但即使在Module#prepend
和Refinements存在之前,也没有理由使用alias
来保留未使用的方法来污染命名空间,Rails abandoned it quite a while ago:
class String old_inspect = instance_method(:inspect) define_method(:inspect) do "I am a string: “#{old_inspect.bind(self).()}”" end end 'abc'.inspect #⇒ 'I am a string: “"abc"”'