ruby - 通过创建新的字符串对象来调用字符串上的方法
问题描述
好的,所以我有一个方法 colourize 在字符串类中动态修补:
class String
@@colours = [[154, 184, 208, 203, 198, 164, 129, 92], [63, 33, 39, 44, 49, 83, 118], [40,41,42,43,211, 210, 209, 208]].tap { |itself| itself.concat(itself.map(&:reverse)) }
define_method(:colourize) do |final = ''|
colour = @@colours.sample
colour_size = colour.size - 1
index, div, val = 0, length / colour_size, ''
div = 1 if div == 0
colour_size -= 1
each_char.with_index do |c, i|
index += 1 if (i % div == 0 && index < colour_size) && i > 1
val.concat("\e[38;5;#{colour[index]}m#{c}")
end
val + "\e[0m" + final
end
end
这会使 String 对象着色(仅在 Linux 系统上的 BASH shell 中测试)。但是我每次都必须编写 colourize 方法。
puts 'Hello World'.colourize
有没有办法修补字符串,以便在创建“Hello World”或将其分配给变量时,默认情况下会调用 colourize 方法?
修补 String#initialize 并不简单。
解决方案
有没有办法修补 String 所以 [...] 默认情况下,它会调用 colourize 方法?
这是一个坏主意。字符串是 Ruby 的基础,就像数组、哈希和符号一样。无论如何,将颜色代码放在每个创建的字符串中,很可能会破坏某些东西。
您应该只在实际打印字符串时添加颜色代码(并且可能只在您打印到 tty 时)。
这将我们带到puts
. 它将给定的对象写入标准输出,并在需要时将它们转换为字符串。不幸的是,字符串不需要任何转换,因此to_s
跳过了对的调用,我们没有方法可以挂钩。
String
但是我们可以修补顶层而不是 patching puts
:
(我upcase
用于演示目的是因为我无法在此处呈现 ANSI 转义序列)
def puts(*args)
Kernel.puts(*args.map { |a| a.is_a?(String) ? a.upcase : a })
end
puts 'hello'
输出:
HELLO
由于修补核心类是一项肮脏的工作,让我们看看是否能找到更清洁的方法。的文档Kernel.puts
说:
相当于
$stdout.puts(obj, ...)
这听起来很有希望:$stdout
作为一个全局变量可以很容易地改变。我们所需要的只是一个提供自定义puts
方法并将任何其他方法委托给原始标准输出的对象。这SimpleDelegator
是为了:
class OutputDecorator < SimpleDelegator
def puts(*args)
super *args.map { |a| a.is_a?(String) ? a.upcase : a }
end
end
试一试吧:
puts 'before'
$stdout = OutputDecorator.new($stdout)
puts 'within'
$stdout = $stdout.__getobj__
puts 'after'
输出:
before
WITHIN
after
推荐阅读
- python - 使用 python 中的子进程运行带有命令行参数的 C#.NET 可执行文件
- performance - Jmeter问题中的Filename.tar.gz文件下载
- java - 微服务中异步处理大量消息
- node.js - 带有 Mongoose 的子文档的聚合查询
- typescript - 在 React Native Expo 中预览上传的文档
- python - 如何在忽略类中使用 pytorch 闪电精度?
- terraform - 创建 VPC 时出错:UnauthorizedOperation
- javascript - 设置 Material UI DataGrid Filter 的 z-index
- parsing - 使用 Elastic App Search 网络爬虫进行解析
- python - 使用 pyomo 和 pao 优化电池容量和运行计划。两阶段随机优化的尝试