このコード スニペットはメソッドをプライベート メソッドとして作成しますが、なぜでしょうか?
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
このコード スニペットはメソッドをプライベート メソッドとして作成しますが、なぜでしょうか?
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
モジュールの外部で定義されたメソッド (いわゆるグローバル メソッド) は、実際には のプライベート インスタンス メソッドとして定義されますObject。そうすれば、 はどこでも呼び出すことができ (すべてが から継承されるためObject)、明示的な受信者なしでのみ呼び出すことができます。
requireこれには、load、puts、print、p、gets、などのメソッドが含まれます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