Ruby:覆盖puts方法

omtl5h9j  于 2022-11-04  发布在  Ruby
关注(0)|答案(4)|浏览(182)

我有一个在IRB中运行的小程序。它最终输出的东西看起来像一个数组,但从技术上讲并不是数组。(类继承自数组。)问题是,当我创建该类的一个示例,例如example = Awesome.new(1,2,3),并且我写“puts example”时,IRB的默认行为是将example的每个元素放在它自己的行上。
所以与其

[1,2,3]

(这是我想要的),IRB弹出这个。

1
2
3

有没有一个聪明的方法来覆盖这个特殊类的puts方法?我试过了,但是没有用。

def puts
  self.to_a
end

你知道我做错了什么吗
更新:所以我尝试了这个,但没有成功。

def to_s
  return self
end

所以当我在IRB中输入“example”时,我得到了我想要的行为(即[1,2,3])。所以我想我可以返回self,但显然我还是搞砸了一些东西。我不明白什么?

4si2a6ki

4si2a6ki1#

你应该重写to_s,它将被自动处理,只要记住从to_s返回一个字符串,它将作为一个魅力。

示例代码段..

class Obj 
  def initialize(a,b)
    @val1 = a 
    @val2 = b 
  end 

  def to_s
    "val1: #@val1\n" +
    "val2: #@val2\n" 
  end 
end

puts Obj.new(123,321);
val1: 123
val2: 321
pieyvz9o

pieyvz9o2#

def puts(o)
  if o.is_a? Array
    super(o.to_s)
  else
    super(o) 
  end  
end

puts [1,2,3] # => [1, 2, 3]

或者只使用p

p [1, 2, 3] # => [1, 2, 3]
gzszwxb4

gzszwxb43#

您最好为类似Array的类实现to_ary方法。puts将调用此方法来获取所有元素。

require 'forwardable'

class Path 
  extend Forwardable
  def_delegators :@list, :<<, :count, :include?, :last, :each_with_index, :map

  def initialize(list = [])
    @list = list
  end

  def to_ary
    self.map.each_with_index{ |e, i| "#{e}, step: #{i}" }
  end
end
rqqzpn5f

rqqzpn5f4#

没有一个答案是关于覆盖Ruby puts方法的,这是这个问题的标题。所以忽略Ben关于数组的具体问题,假设你已经很好地掌握了Ruby scope,让我们考虑一下一般情况:

**首先,注意:**您可能并不真的需要全局覆盖puts方法。这样做的理由很少。因为如果您在顶层的全局范围内定义了puts方法,您将覆盖默认的puts功能,用于您加载的 * 所有Ruby代码 *(例如,您的脚本,以及您的脚本需要的所有库)。这很容易产生意想不到的结果。想象一下覆盖raise-您可以......但您不应该。
**第二:**知道你在覆盖什么总是很好的--另一个回答很有帮助地指出,method(:puts)表明你在覆盖Kernel.puts。你可能想在你的覆盖中调用它。或者你可以调用super,它调用你已经覆盖的方法。
**第三:**注意Kernel.puts行为:它可以接受多个参数,有时称为varargs。它返回nil。因此,也许您的覆盖也应该这样做。我还注意到它有一个odd tendency to unwrap arrays(可能与接受varargs有关)-所以我将重现该行为,只是因为。

如果你真的想在全局覆盖看跌期权,你可以这样做:


# Prefix each line of my puts output (including strings with "\n")

def puts *args
  if (args.length>1) then
    args.each { |a| puts a }
  elsif (args[0].is_a?(Array)) then # unwrap arrays like Kernel.puts
    puts args[0]
  else
    lines = "#{ args[0] }".split("\n")
    lines.each { |line| Kernel.puts "PREFIX: #{ line }" }
  end
  return nil
end

相关问题