Ruby 在保持inspect输出的同时覆盖到_s

Ruby 在保持inspect输出的同时覆盖到_s,ruby,oop,overriding,Ruby,Oop,Overriding,当我使用puts时,我重写了to_方法以获得漂亮的输出,但同时我似乎失去了检查对象的能力。是否有方法在覆盖到_s时获得inspect的正常输出 class Person attr_accessor :first, :last, :birthdate def initialize(first=nil, last=nil, birthdate=nil) @first, @last, @birthdate = first, last, birthdate end def age

当我使用puts时,我重写了to_方法以获得漂亮的输出,但同时我似乎失去了检查对象的能力。是否有方法在覆盖到_s时获得inspect的正常输出

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>
班级人员
属性访问器:第一个、最后一个、出生日期
def初始化(第一次=零,最后一次=零,出生日期=零)
@first,@last,@birthdate=first,last,birthdate
结束
定义年龄
如果生日
时间,现在,生日
其他的
0
结束
结束
def至美国
“{@first}{@last}({age})”
结束
结束
我=人。新(“彼得”,“玛丽”,1962年)
彼得·玛丽(50岁)
p me.inspect>>“彼得·玛丽(50)”
#需要#

我认为默认情况下,inspect使用to_s方法

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

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

如果不需要对象的地址,可以提供自己的inspect,以实现几乎相同的行为:

class Person
  def inspect
    vars = self.instance_variables.
      map{|v| "#{v}=#{instance_variable_get(v).inspect}"}.join(", ")
    "<#{self.class}: #{vars}>"
  end
end
然后在irb或您的脚本中:

require 'awesome_print'
ap Person.new("John")
还有一个内置的
pp
库,具有类似的用途。但它仍然不能免疫(至少在Ruby 1.9.2-p290中)重写

pp
的一个快速示例:

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

这里是Aleksander的解,第一个p应该给_s覆盖,但是没有,你必须明确地调用第二个p中的_s,以得到我想要的结果。我也不确定这个检查是否会给出与原来的检查相同的结果,因为它包含更复杂的对象,我会在家里尝试。还有更好的吗? 我知道非常棒的打印宝石,但是对于像这样的基本东西,你不需要包括宝石

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>"
班级人员
def初始化(第一次=零,最后一次=零,出生日期=零)
@first,@last,@birthdate=first,last,birthdate
结束
#to_s的新实现
def至美国
“{@first}{@last}”
结束
def检查
vars=self.instance\u变量。
map{v}“{v}={instance_variable_get(v.inspect}”}.join(,”)
"" 
结束
结束
我=新的人(“约翰”)
p我-->
给我一封信-->“约翰”
请检查-->“”
编辑:我刚刚尝试了awesome_print,我很高兴,担心我必须使用IRB来利用它,但事实并非如此,我在我的编辑器中运行我的脚本

require 'awesome_print'
ap me --> 
#<Person:0x027efe20
    @birthdate = nil,
    @first = "John",
    @last = nil
>
要求“绝妙打印”
ap我-->
#
按照Aleksander的建议,使用pretty_print进行编辑,不会干扰覆盖到的

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>
require'PP'
班主任
def初始化(第一次=零,最后一次=零,出生日期=零)
@first,@last,@birthdate=first,last,birthdate
结束
#to_s的新实现
def至美国
“{@first}{@last}”
结束
结束
我=新的人(“约翰”)
pp我-->
警告我。漂亮的检查-->

佩里,这里是我试图让alias或alias_方法工作的众多组合之一,如果你认为这是可行的,你能提交一个工作片段吗

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>"
班级人员
属性访问器:第一个、最后一个、出生日期
def初始化(第一次=零,最后一次=零,出生日期=零)
@first,@last,@birthdate=first,last,birthdate
结束
别名old_to_s to_s
def检查
老外
结束
def至美国
“{@first}{@last}”
结束
结束
我=新的人(“彼得”)
p我-->#
请检查-->“#”

此错误报告讨论了相同的问题:但是我没有看到票证上的任何进展。因此,这是一个错误,我没有意识到..,感谢您提供的链接。您希望使用alias_方法(查找它)来“保存一份”旧to_方法,然后覆盖inspect方法来简单地调用旧to_方法。您也可以只使用alias_方法在覆盖到_s之前将旧的to_s别名为“inspect”——如果可行,这是最简单的方法。Perry不可行,尝试了alias和alias_方法的所有组合,你要么得到两个的美化输出,要么得到bothI的非美化输出。bothI建议的基本上与另一个回答者给出的内容相同,只是有一些小的变化。我认为您可能做得不太对--也许您应该发布您试用过的代码。这不起作用。默认的#to_s不包括实例变量。谢谢,但是。。。p(或puts)不会给出不变的相同结果,并且您的代码会给出以下结果,因此to#s Pretifier不再有效“你能详细说明一下吗?”我不知道预期的行为与提供的代码的行为相比是什么。只需使用更复杂的对象进行尝试,p对象会提供对象以外的其他输出。检查,无论如何,您的代码不起作用,您尝试过吗?它给出了对象表示,而不是修饰和对象表示感谢,这是朝着正确方向迈出的一步,但不是完全正确的。我把结果放在一个答案中,我可以给出布局。如果有循环引用,则失败,例如:丈夫=人。新;妻子=人。新的;丈夫、配偶=妻子;妻子.配偶=丈夫re:
awesome\u print
还有
pp
(pretty\u print)库,它与Ruby捆绑在一起,具有类似的用途。但是
pp
是基于检查的,所以将
更改为
会破坏
pp
的结果。这不会发生在
awesome\u print
上,这就是我推荐使用它的原因。试用过的pp和pretty\u inspect,它们不会与重写的to\s相互恐惧,它在内核中,很好,但您必须需要它,编辑答案以备将来参考,并将您的响应标记为答案,谢谢你的帮助-我尝试了你提供的例子,得到了不同的结果。你使用哪个Ruby版本?另外:你需要'PP'还是'PP'?ruby-v给出了ruby 1.9.3p0(2011-10-30)[i386-mingw32],需要'PP'给出了与需要'PP'相同的结果,会有区别吗?也许是操作系统,我用的是Windows7
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>"