でテスト
は、Rubyでいることに注目することによって開始レッツ、クラスFoo
で宣言方法a
では、私がにFoo
の任意のインスタンスを保護されたメソッドを呼び出すことができます。
私たちがクラスFoo
で宣言されたメソッドにいるかどうかをRubyがどのように判断しますか?これを理解するには、メソッド呼び出しの内部を掘り下げなければなりません。私はMRIのバージョン2.2からの例を使用しますが、おそらく動作と実装は他のバージョンでも同じです(私はこれをJRubyやRubiniousでテストした結果を見たいと思っています)。
Rubyはrb_call0
でこれを行います。コメントに示されているように、self
を使用して、保護されたメソッドを呼び出すことができるかどうかを判断します。 self
は、現在のスレッドの呼び出しフレーム情報からrb_call
に取得されます。次にrb_method_call_status
では、この値self
が保護されたメソッドが定義されている同じクラスであることを確認します。
ブロックは問題を多少混乱させます。 Rubyメソッドのローカル変数は、そのメソッドで宣言されたブロックによって取得されることに注意してください。これは、ブロック内で、self
がメソッドが呼び出された同じself
であることを意味します。例を見てみましょう:
class Foo
def give_me_a_block!
puts "making a block, self is #{self}"
Proc.new do
puts "self in block0 is #{self}"
end
end
end
proc = Foo.new.give_me_a_block!
proc.call
がこれを実行すると、我々はFoo
の同じインスタンスは、我々は完全に異なるオブジェクトからPROCと呼ばれるにもかかわらず、すべてのレベルで同じである参照してください。
これで、同じクラスの別のインスタンスで保護されたメソッドをメソッド内のブロック内から呼び出すことができる理由を理解しました。
ここで、&:bar
で作成されたprocがこれを行うことができない理由を見てみましょう。メソッドの引数の前に&
の符号を付けるときは、2つのことを行います:rubyにこの引数をブロックとして渡し、to_proc
を呼び出すように指示します。
これは、メソッドSymbol#to_proc
を呼び出すことを意味します。このメソッドはCで実装されていますが、Cメソッドを呼び出すと、現在のフレームのself
へのポインタがそのCメソッドの受信者になります。この場合は、シンボル:bar
になります。だから我々はfoo
のインスタンスを見ているのですが、のように、Symbolクラスのメソッドであるかのようになり、保護されたメソッドを呼び出すことはできません。
これは一口ですが、うまくいけば十分です。どのように私がそれを改善するかもしれないかについての提案があれば教えてください!
出典
2015-12-14 02:30:58
jjm
これは大きな質問です。誰かが私たちを啓発できることを祈りましょう。 –
本当に良い質問です。私が見ることのできる違いは、最初のブロックのローカル変数で 'bar'を呼び出すだけですが、procで変数を指定しないと呼び出すことができます。それでも良い理由があるのかどうかは不思議です。 – DaniG2k
'foo'変数なしでテストされていますが、それでも同じことがあります。私は、これらの2つのメソッドが同等の結果を出力する必要があるとは思いますが、これはprocsの呼び出し方法と関係があります。 – DaniG2k