假设我想puts
大量大写的字符串,但为了简洁起见,我想写puts(string)
而不是每次都 puts(string.upcase)
。
有没有办法让我像这样重新定义puts
仅在一个 block 内?
# This will puts as normal
puts "abc"
# => abc
# This will puts an upcased string, but it's too verbose
puts "abc".upcase
# => ABC
# I want to do something like this, which will override the puts method for code run within the block
def always_upcase_strings(&block)
def puts(string)
super(string.upcase)
end
end
always_upcase_strings do
puts "abc"
puts "def"
puts "ghi"
end
puts "xyz"
# => ABC
# => DEF
# => GHI
# => xyz
上面的示例经过简化 - 在我的例子中,我没有使用 puts
,而是我自己编写的方法。
最佳答案
关于second thoughts ,这是一个更好的答案:
def always_upcase_strings(&block)
anon_class = Class.new do
def puts(str)
super(str.upcase)
end
end
anon_class.new.instance_eval(&block)
end
always_upcase_strings do
puts "abc" #=> "ABC"
puts "def" #=> "DEF"
puts "ghi" #=> "GHI"
end
puts "xyz" #=> "xyz"
这个creates具有所需方法覆盖的临时类(匿名,因为它不需要名称)。
然后,在此类实例的上下文中调用生成的 block 。
除了比我的“重新定义-取消定义-重新定义方法”解决方案更容易混淆之外,这种方法还有一个额外的优点,即它是线程安全的。因此,例如,如果在调用该方法时运行并行测试,您不会得到奇怪的行为。
...但我仍然坚持我最初的说法,即在 block 内重新定义方法是非常令人惊讶的行为。同事可能不会喜欢你选择这种设计模式(除非它是以有限的方式完成的,并且有充分的理由!)
关于ruby - 有没有办法在 block 内重新定义方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55928251/