【问题标题】:Implement to_s of Array in Ruby在 Ruby 中实现数组的 to_s
【发布时间】:2025-12-07 09:15:02
【问题描述】:

Ruby 的 Array 类具有内置方法 to_s 可以将数组转换为字符串。此方法也适用于多维数组。这个方法是如何实现的?

我想知道它,所以我可以重新实现一个方法my_to_s(ary),它可以接收多维并将其转换为字符串。但不是像这样返回对象的字符串表示

[[[1,2,3, Person.new('Mary')]],[4,5,6,7], Person.new('Paul'),2,3,8].to_s
# [[[1, 2, 3, #<Person:0x283fec0 @name='Mary']], [4, 5, 6, 7], #<Person:0x283fe30 @name='Paul'>, 2, 3, 8]   

my_to_s(ary) 应该在这些对象上调用 to_s 方法,以便它返回

my_to_s([[[1,2,3, Person.new('Mary')]],[4,5,6,7], Person.new('Paul'),2,3,8])
# [[[1, 2, 3, Student Mary]], [4, 5, 6, 7], Student Paul>, 2, 3, 8]

【问题讨论】:

  • 我其实相信你只是想覆盖Person#to_s来返回"Student #{self.name}"字符串。

标签: ruby algorithm recursion multidimensional-array tostring


【解决方案1】:

对于嵌套元素,它只分别调用to_s

def my_to_s
  case self
  when Enumerable then '[' << map(&:my_to_s).join(', ') << ']'
  else 
    to_s # or my own implementation
  end
end

这是一个人为的例子,如果这个 my_to_s 方法是在非常 BasicObject 上定义的,那么它几乎可以工作。


正如 Stefan 所建议的,人们可能会避免猴子路径:

def my_to_s(object)
  case object
  when Enumerable then '[' << object.map { |e| my_to_s(e) }.join(', ') << ']'
  else 
    object.to_s # or my own implementation
  end
end

更多面向对象的方法:

class Object
  def my_to_s; to_s; end
end

class Enumerable
  def my_to_s
    '[' << map(&:my_to_s).join(', ') << ']'
  end
end

class Person
  def my_to_s
    "Student #{name}"
  end
end

【讨论】:

  • object.map { |o| my_to_s(o) } 避免猴子补丁。
  • 你可能想用'['']'包围嵌套输出。
  • 对于更多面向对象的方法,您可以将my_to_s 别名为to_sObject 并在Enumerable 中覆盖它
  • @Stefan alias_method 为我工作。 class Object; alias_method :my_to_s, :to_s; end; 5.my_to_s"#&lt;Fixnum:0x0000000000000b&gt;"。啊!它可以工作,但它严格映射到Object#to_s
  • @Stefan 是的,看起来多态性被破坏了,它只是产生了到Object#to_s 的“硬链接”。好笑。