Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 模拟默认对象#检查输出?_Ruby - Fatal编程技术网

Ruby 模拟默认对象#检查输出?

Ruby 模拟默认对象#检查输出?,ruby,Ruby,为了解决这个问题,我们必须在对象上定义一个inspect方法: class << o def to_s; @str; end end p o.to_s # => "foo" p o # => foo irb>o=Object.new.tap{o|o.instance_variable_set:@foo,“bar”} #=> # irb>def o.to_@傅;结束;o #=>巴 irb>模块MyInspect irb>def检查 irb>vars=instance_

为了解决这个问题,我们必须在对象上定义一个
inspect
方法:

class << o
  def to_s; @str; end
end
p o.to_s # => "foo"
p o # => foo
irb>o=Object.new.tap{o|o.instance_variable_set:@foo,“bar”}
#=> #
irb>def o.to_@傅;结束;o
#=>巴
irb>模块MyInspect
irb>def检查
irb>vars=instance_variables.map do|n|
irb>“#{n}=#{instance_variable_get(n).inspect}”
irb>结束
irb>“#”%[self.class,object_id,vars.join(',')]
irb>结束
irb>结束
irb>o.extend MyInspect
#=> #
编辑:看来我基本上想到了你已经做过的事情。不过,您和我的对象id表示方式与原始对象id表示方式不同


让我调查一下是否有任何方法可以绑定到官方实现并使用它

默认的
inspect
方法非常复杂,因为它需要正确处理对自身的递归调用。下面是一个基于源代码的实现,它忽略了存在的
to\u s

irb> o = Object.new.tap{ |o| o.instance_variable_set :@foo, "bar" }
#=> #<Object:0x00000102849600 @foo="bar">

irb> def o.to_s; @foo; end; o
#=> bar

irb> module MyInspect
irb>   def inspect
irb>     vars = instance_variables.map do |n|
irb>       "#{n}=#{instance_variable_get(n).inspect}"
irb>     end
irb>     "#<%s:0x%x %s>" % [self.class,object_id,vars.join(', ')]
irb>   end
irb> end

irb> o.extend MyInspect
#=> #<Object:0x81424b00 @foo="bar">
模块默认检查
当前线程[:已检查的_对象]={}
def检查的对象
线程当前[:已检查的对象]
结束
def检查\u递归\u保护
已检查对象[对象\u id]=真
开始
产量
确保
已检查对象。删除对象\u id
结束
结束
def检查_递归?
检查对象[对象id]
结束
def检查
prefix=“#”如果检查递归?
#否则,收集IVAR并显示它们。
部分=[]
检查\u递归\u保护do
实例_variables.each do | var|

parts要使数字与原始实现匹配,只需将object_id左移一位,如下所示:

class Foo

  include DefaultInspect

  def to_s
    @foo
  end
end

f = Foo.new
f.instance_eval { @foo = f }
p f     #=> #<Foo:0x8042ad58 @foo=#<Foo:0x8042ad58 ...>>

(object\u id)您使用的是哪个版本的Ruby?object\u id实际上是MRI中对象的
(void*)
,在jruby中是一个类似的指针引用。在普通Ruby代码中是无法访问的。这很奇怪。
class << o
  def inspect
    vars = instance_variables.collect { |v| v.to_s << "=#{instance_variable_get(v).inspect}"}.join(", ")
    "#<#{self.class}:0x#{object_id} #{vars}>"
  end
end
irb> o = Object.new.tap{ |o| o.instance_variable_set :@foo, "bar" }
#=> #<Object:0x00000102849600 @foo="bar">

irb> def o.to_s; @foo; end; o
#=> bar

irb> module MyInspect
irb>   def inspect
irb>     vars = instance_variables.map do |n|
irb>       "#{n}=#{instance_variable_get(n).inspect}"
irb>     end
irb>     "#<%s:0x%x %s>" % [self.class,object_id,vars.join(', ')]
irb>   end
irb> end

irb> o.extend MyInspect
#=> #<Object:0x81424b00 @foo="bar">
module DefaultInspect

    Thread.current[:inspected_objects] = {}

    def inspected_objects
      Thread.current[:inspected_objects]
    end

    def inspect_recursion_guard
      inspected_objects[object_id] = true
      begin
        yield
      ensure
        inspected_objects.delete object_id
      end
    end

    def inspect_recursion?
      inspected_objects[object_id]    
    end

    def inspect
      prefix = "#<#{self.class}:0x#{self.__id__.to_s(16)}"

      # If it's already been inspected, return the ...
      return "#{prefix} ...>" if inspect_recursion?

      # Otherwise, gather the ivars and show them.
      parts = []

      inspect_recursion_guard do
        instance_variables.each do |var|
          parts << "#{var}=#{instance_variable_get(var).inspect}"
        end
      end

      if parts.empty?
        str = "#{prefix}>"
      else
        str = "#{prefix} #{parts.join(' ')}>"
      end

      str.taint if tainted?

      return str
    end

end
class Foo

  include DefaultInspect

  def to_s
    @foo
  end
end

f = Foo.new
f.instance_eval { @foo = f }
p f     #=> #<Foo:0x8042ad58 @foo=#<Foo:0x8042ad58 ...>>
(object_id << 1).to_s(16)