4

我只学习了 Ruby 的深层部分几个月,所以如果这是一个有点愚蠢的问题,我深表歉意。我正在尝试递归迭代一个可能包含嵌套数组的数组,因此我需要检查当前元素的类型。我有以下代码作为一个小测试:

arr = [ 1..2, [3..4, [5..6]], [7..8, [9..10]] ]

arr.each do |node|
  p node.class
  p node.instance_of? Array
end

当我运行它时,我得到以下输出:

Range
false
Array
false
Array
false

我希望最后两个返回 True,因为我有一个包含 Range 和两个嵌套数组的数组。

更奇怪的是,如果我写以下内容:

node.class.name == "Array"

它应该返回 True。

这里发生了什么事?

红宝石版本: MRI 1.9.3-p194

注意:我最终意识到这是由于我使用模块命名我的代码以避免代码冲突的方式,就像这样,但也以一种顽皮的方式验证对象身份:

module MyProg
  class MyClass
    attr_reader :my_array

    def initialize(size)
      @my_array = Array.new(size)
    end
  end
end

MyProg::MyClass.new

这样做会隔离您的代码,但会导致从您的命名空间下开始解析所有类查找。这意味着在上面的示例中,my_array.class实际上会解析为MyProg::Array而不是全局 Array 类。

如果你像这样命名空间并且你仍然想使用这个方法,你可以通过在类之前使用双冒号全局标识符来强制 Ruby 从全局命名空间开始查找来解决它:

arr.is_a? ::Array
arr.is_a? ::String

然而,鉴于 Ruby 的 Duck Typing 能力(以及以后更好的代码维护),您应该按照下面彼得的建议测试对象的行为。因此,我将他的答案标记为正确,以便为学习者提供一些极好的帮助!

4

3 回答 3

3

你的意思是is_a?,这是一个更通用的测试,看看是否node是 type ,而不是你提到Array的特定类的特定实例。Array有关更多详细信息,请参见此处。但如果你只是使用is_a?一切都会有意义。

于 2012-07-03T22:38:55.337 回答
3

我写了另一个答案,但一个主要问题是 - 你为什么要这样做?为什么不直接调用flatten数组来获取条目呢?或者,改为检查对象的行为。您可能需要详细说明您的需求。

于 2012-07-03T23:21:46.097 回答
1

我运行了您的代码并得到了这些结果。

Range
false
Array
true
Array
true

我正在运行 ruby​​ 1.9.3p125

于 2012-07-03T22:41:41.583 回答