我知道ObjectSpance得到的字符串如下:
strings = ObjectSpace.each_object(String);
但它不是红宝石中的所有字符串;如果我想得到像这样的local_variables:
module My
def self.test
a = "I'm a string"
end
end
得到" I'm a string"
,ObjectSpace可以做到吗?
答案 0 :(得分:0)
在定义它们的范围内,字符串“不知道”哪些局部变量(如果有)保持其值。也就是说,不能仅从字符串获得该信息。例如,对于a=['cat', 'dog']
,'cat'
和'dog'
由无局部变量保留,在a = b = 'cat'
中,'cat'
由两个局部变量保存。而且,两个相同(未冻结)的字符串是不同的对象。因此,即使我们可以某种方式使用ObjectSpace.each_obect(String)
以某种方式钻进所有类实例的方法(我们不能),我们也无法检索所需的信息。
我们也不能在方法中识别局部变量,然后确定它们的值。这是因为它们可能存在的唯一时间是在调用方法之后和返回之前,并且该方法之外的信息不可用。而且,它可能在执行方法期间发生变化。
在任何时间点,可以获得局部变量及其值(但仅限于方法内),如下所示。
def at
b = 3
c = 4
local_variables.map { |v| [v, binding.local_variable_get(v)] }.to_h
end
at
#=> {:b=>3, :c=>4}
然而,回答OP的问题没有任何帮助。
情况有所不同是我们被要求在给定的时间点识别每个现有类的每个现有实例的所有实例变量及其值(因此我们可以限制我们的注意持有字符串的实例变量)。
例如,假设我们定义了以下类。
class Z
def initialize(str1, str2)
@z1, @z2 = str1, str2
end
end
并创建此类的两个实例。
mimi_fufu = Z.new 'mimi', 'fufu'
#=> #<Z:0x00000001269160 @z1="mimi", @z2="fufu">
fido_biff = Z.new 'fido', 'biff'
#=> #<Z:0x000000012772b0 @z1="fido", @z2="biff">
现在,ObjectSpace.each_object(Class)
返回当前定义的所有类的数组,一个是Z
,ObjectSpace.each_object(Z)
返回Z
所有实例的数组。因此,我们可以执行以下计算以获得Z
的所需信息(因此,对于每个其他现有类)。
ObjectSpace.each_object(Z).map do |inst|
{ instance: inst,
inst_vars: inst.instance_variables.each_with_object({}) { |iv,h|
h[iv] = inst.instance_variable_get(iv) } }
end
#=> [{:instance=>#<Z:0x00000001269160 @z1="mimi", @z2="fufu">,
# :inst_vars=>{:@z1=>"mimi", :@z2=>"fufu"}},
# {:instance=>#<Z:0x000000012772b0 @z1="fido", @z2="biff">,
# :inst_vars=>{:@z1=>"fido", :@z2=>"biff"}}]