このコード スニペットはメソッドをプライベート メソッドとして作成しますが、なぜでしょうか?
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)
eval
eval
A.class
42.send(:eval)
代わりに行うこともできますが、まったく同じメソッドを呼び出すことになるためputs('Hello')
、結果はまったく同じです。42.send(:puts, 'Hello')
ちなみに、たとえそれができたとしても、あなたが望むことはまだできません。A.class
はただClass
(任意のclass
クラスの は常に) であるため、期待どおりに動作した場合、メソッドは ではなく で定義されます。 Class
Class
A