在保持inspect的输出的同时覆盖to_s

时间:2012-03-01 21:51:28

标签: ruby oop override

我覆盖to_s方法,以便在我使用puts时得到漂亮的输出,但同时我似乎失去了检查对象的能力。有没有办法在覆盖to_s时获得正常的检查输出?

class Person
  attr_accessor :first, :last, :birthdate
  def initialize(first=nil, last=nil, birthdate=nil)
    @first, @last, @birthdate = first, last, birthdate
  end
  def age
    if birthdate
      Time.now.year-birthdate
    else
      0
    end
  end
  def to_s
    "#{@first} #{@last} (#{age})"
  end
end

me = Person.new("Peter", "Marien", 1962)
p me  >>Peter Marien (50)
p me.inspect  >>"Peter Marien (50)"

#Need #<Person:0x1ec2550 @first="Peter", @last="Marien", @birthdate=1962>

4 个答案:

答案 0 :(得分:4)

Ruby文档clearly states,默认情况下inspect使用to_s作为输出。

如果您不需要对象的地址,您可以提供自己的检查,以便具有几乎相同的行为:

class Person
  def inspect
    vars = self.instance_variables.
      map{|v| "#{v}=#{instance_variable_get(v).inspect}"}.join(", ")
    "<#{self.class}: #{vars}>"
  end
end

但你也可以安装一个名为awesome_print的宝石,它会提供非常好的输出。 首先在控制台中:

$ gem install awesome_print

然后在irb或你的脚本中:

require 'awesome_print'
ap Person.new("John")

还有一个内置的pp库,其目的相似。仍然不能免于(至少在Ruby 1.9.2-p290中)覆盖to_s

pp的简短示例:

require 'pp'
pp Person.new("John")

答案 1 :(得分:0)

我相信默认情况下使用to_s方法。

但是,您也可以覆盖inspect,包括在覆盖之前将旧的to_s方法别名化。

答案 2 :(得分:0)

这里是Aleksander的解决方案,第一个p应该给出被覆盖的to_s但是没有,你必须像第二个p中那样明确地调用to_s来得到我想要的结果。我也不确定这个检查会给出与原始的更复杂物体相同的结果,我会在家里试试。谁还有更好的射门? 我知道awesome_print宝石,但恕我直言,你不应该包含宝石。

class Person

  def initialize(first=nil, last=nil, birthdate=nil) 
    @first, @last, @birthdate = first, last, birthdate 
  end 

  # New implementation of to_s 
  def to_s 
    "#{@first} #{@last}" 
  end

  def inspect 
    vars = self.instance_variables. 
      map{|v| "#{v}=#{instance_variable_get(v).inspect}"}.join(", ") 
    "<#{self.class}: #{vars}>" 
  end 

end 

me = Person.new("John")
p me         #--><Person: @first="John", @last=nil, @birthdate=nil>
p me.to_s    #-->"John "
p me.inspect #-->"<Person: @first=\"John\", @last=nil, @birthdate=nil>"

编辑:我刚尝试了awesome_print,我很高兴,我担心我不得不使用IRB来使用它,但事实并非如此,我在编辑器中运行我的脚本

require 'awesome_print'
ap me --> 
#<Person:0x027efe20
    @birthdate = nil,
    @first = "John",
    @last = nil
>

按照Aleksander的建议使用pretty_print进行编辑,不会干扰被覆盖的to_s

require 'PP'
class Person

  def initialize(first=nil, last=nil, birthdate=nil) 
    @first, @last, @birthdate = first, last, birthdate 
  end 

  # New implementation of to_s 
  def to_s 
    "#{@first} #{@last}" 
  end
end 

me = Person.new("John")
pp me                   #--> <Person: @first="John", @last=nil, @birthdate=nil>
warn me.pretty_inspect  #--> <Person: @first="John", @last=nil, @birthdate=nil>

答案 3 :(得分:0)

Perry,这是我试图获得别名或alias_method工作的众多组合之一,如果您认为这样做,可以提交一个工作片段吗?

class Person
  attr_accessor :first, :last, :birthdate
  def initialize(first=nil, last=nil, birthdate=nil)
    @first, @last, @birthdate = first, last, birthdate
  end

  alias old_to_s to_s
  def inspect
    old_to_s
  end
  def to_s
    "#{@first} #{@last}"
  end

end

me = Person.new("Peter")
p me         #-->#<Person:0x1da26b8>
p me.inspect #-->"#<Person:0x1da26b8>"