6

次の「B」には「A」からはアクセスできないのに、メイン環境からはアクセスできるのはなぜですか?

module A; end
A.instance_eval{B=1}

B #=> 1
A::B #=> uninitialized
4

4 に答える 4

4

(強調鉱山)のドキュメントinstance_evalから:

レシーバー (obj) のコンテキスト内で、Ruby ソース コードを含む文字列または指定されたブロックを評価します。コンテキストを設定するために、コードの実行中に変数 self が obj に設定され、コードがobj のインスタンス変数にアクセスできるようになります。

ここではこれ以上何もしません。特に、定数の代入は、ブロックの外側のコンテキストで実行されます。観察:

irb(main):001:0> module A
irb(main):002:1>   module B; end
irb(main):003:1>   B.instance_eval { C = 1 }
irb(main):004:1> end
=> 1
irb(main):006:0> A::C
=> 1
于 2012-04-09T19:49:42.450 に答える
4

なぜなら 。. .

. . . クラスまたはモジュール内で定義されていない定数には、グローバル スコープが与えられます。

定数の定義で重要なのは、現在のレシーバーや の値ではなく、囲んでいるレキシカル スコープですself

于 2012-04-09T19:54:47.343 に答える
3

これを行う慣用的な方法は次のようになります

 A.const_set(:B, 1)
 A::B #=> 1

Ruby 1.8 と 1.9.2+ (1.9.1 では異なります) では、なぜ機能しないのかというと、定数ルックアップはレキシカル スコープです。説明付きの良いブログ投稿を見つけました。引用するには:

これらの規則は、定数の定義とルックアップに適用されることに注意してください。1.8 および 1.9.2 では、class_evaluated ブロックで定義された定数は、レシーバーのスコープではなく、囲んでいるレキシカル スコープで定義されます。

についても同様ですinstance_eval

于 2012-04-09T19:43:46.257 に答える
1
module A; end
A.class_eval{B=1}
B # Undefined
A::B # 1

なぜそれが機能するのかについては、よくわかりません。Small Eigen Collider のような非常にメタなフレームワークを作成するときは、このようなメタプログラミングをときどき使用しますが、日常業務では使用しません。

于 2012-04-09T23:42:01.187 に答える