2

このコード スニペットはメソッドをプライベート メソッドとして作成しますが、なぜでしょうか?

a = %q{def hello() "Hello there!" end}
class A; end
A.class.send(:eval, a)
A.new.hello #=> NoMethodError: private method `hello' called for A

プラットフォーム: ruby​​ 1.9.3p125、テスト済みpry

4

1 に答える 1

5

モジュールの外部で定義されたメソッド (いわゆるグローバル メソッド) は、実際には のプライベート インスタンス メソッドとして定義されますObject。そうすれば、 はどこでも呼び出すことができ (すべてが から継承されるためObject)、明示的な受信者なしでのみ呼び出すことができます。

requireこれには、loadputsprintpgets、などのメソッドが含まれますeval。(注: それらのほとんどは、実際にはで定義されKernel、混合されてObjectいますが、効果と目的は同じです。)

あなたの場合、モジュールの外側でメソッドa定義しています。文字列にモジュールについての言及はありません。あなたが呼びかけevalているという事実は、A.classまったく無関係です。上で述べたように:は便利な理由でeval定義されたグローバルメソッドです (どこでも呼び出される可能性があります)。これは、グローバル プライベート メソッドを呼び出す非常に複雑なObject方法です。uated 文字列のコンテキストを何らかの魔法のように に設定するわけではありません。A.class.send(:eval)evalevalA.class

42.send(:eval)代わりに行うこともできますが、まったく同じメソッドを呼び出すことになるためputs('Hello')、結果はまったく同じです。42.send(:puts, 'Hello')

ちなみに、たとえそれできたとしても、あなたが望むことはまだできません。A.classはただClass(任意のclassクラスの は常に) であるため、期待どおりに動作した場合、メソッドは ではなく で定義さます。 ClassClassA

于 2012-09-20T00:09:12.897 に答える