我使用块来创建像这样的值
some_block = BlockClass.new {|b|
b.one = 1
b.two = 2
b.three = 3
}
以下是BlockClass
class BlockClass
attr_accessor :one
attr_accessor :two
attr_accessor :three
def initialize
yield self if block_given?
end
end
我需要一种迭代some_block
的方法,并在不必执行的情况下打印块中的所有值
puts some_block.one
puts some_block.two
puts some_block.three
有没有办法迭代块中的值?
答案 0 :(得分:1)
首先,块中的b
参数为nil,因此您将获得
NoMethodError: undefined method `one=' for nil:NilClass`
要解决此问题,您可以将yield if block_given?
更改为yield(self) if block_given?
,这会将self
作为第一个参数传递给该块。
如果您需要b.one = ..., b.two = ...
语法,则应使用OpenStruct
:
require 'ostruct'
class BlockClass < OpenStruct
def initialize
super
yield(self) if block_given?
end
end
您可以通过调用Hash
来获取内部marshal_dump
的转储:
some_block = BlockClass.new {|b|
b.one = 1
b.two = 2
b.three = 3
}
some_block.marshal_dump # => {:one=>1, :two=>2, :three=>3}
然后您可以迭代值:
some_block.marshal_dump.each_pair do |k, v|
puts "the value of #{k} is #{v}"
end
答案 1 :(得分:0)
您的广告代码需要1个参数b
,但您的yield语句不能传递任何内容。也许您的意思是yield self if block_given?
?
此外,如果你想要&#34;迭代&#34;,你需要一个可枚举的东西集合,比如Array
或Hash
。实际上,one
,two
和three
与您的BlockClass
完全无关。
你可以遍历BlockClass
的所有方法:
(some_block.methods).each do |method_name|
puts some_block.send(method_name)
end
但这并不像你正在寻找的那样。也许Initialize a Ruby class from an arbitrary hash, but only keys with matching accessors可能有帮助吗?