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

Range と 2 つのネストされた Array を含む Array があるので、最後の 2 つは True を返すと予想していました。

さらに奇妙なのは、次のように書く場合です。

node.class.name == "Array"

当然のことながら、True を返します。

ここで何が起こっているのですか?

Ruby バージョン: 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 機能を考えると (そして、後でコードをより適切に保守するために)、以下の Peter の提案に従って、実際にオブジェクトの動作をテストする必要があります。そのため、学習者に与えられたいくつかの優れたヘルプに対して、彼の答えを正しいものとしてマークしています!

4

3 に答える 3

3

別の回答を書きましたが、大きな質問の 1 つは、なぜこれを行うのかということです。flatten代わりに、単に配列を呼び出して、エントリを取得してみませんか? または、代わりにオブジェクトの動作を確認してください。必要なものについて、より詳細な情報を提供する必要がある場合があります。

于 2012-07-03T23:21:46.097 に答える
3

これは、言及した特定のクラスの特定のインスタンスではなく、タイプが であるis_a?かどうかを確認するためのより一般的なテストです。詳しくはこちらをご覧ください。しかし、すべてを使用するだけでは意味がありません。nodeArrayArrayis_a?

于 2012-07-03T22:38:55.337 に答える
1

私はあなたのコードを実行し、これらの結果を得ました.

Range
false
Array
true
Array
true

ルビー1.9.3p125を実行しています

于 2012-07-03T22:41:41.583 に答える