class Example
private
def example_test
puts 'Hello'
end
end
e = Example.new
e.example_test
もちろん、これは機能しません。なぜなら、明示的な受信者-例のインスタンス(e
)を指定したからです。これは「プライベートルール」に反します。
しかし、なぜRuby this:
class Foo
def public_m
self.private_m # <=
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
public_m
メソッド定義(つまりself
)内の現在のオブジェクトはFooのインスタンスです。では、なぜ許可されないのでしょうか?これを修正するには、self.private_m
をprivate_m
に変更する必要があります。しかし、なぜこれが異なるのか、self
はpublic_m
内のFooのインスタンスではありませんか?ベアワードprivate_m
呼び出しの受信者は誰ですか?それはself
ではありません-実際に何を省略しているのですか、Rubyはあなたのためにそれを行います(自分でprivate_mを呼び出す)?
混乱させすぎないように願っています。Rubyにはまだ新鮮です。
編集:すべての答えをありがとう。それらをすべてまとめると、(最終的に)明白な(そしてRubyのようなものを見たことがない人にとってはそれほど明白ではない)を理解することができました:self
自体が明示的および暗黙的なレシーバーであり、それが違いを生むことができます。したがって、プライベートメソッドを呼び出す場合は、2つのルールがあります:self
は暗黙的なレシーバーであり、そのselfは現在のクラスのインスタンスである必要があります(その場合はExample
このメソッドの実行中にインスタンスメソッド定義内にある場合はself)。間違っている場合は修正してください。
class Example
# self as an explicit receiver (will throw an error)
def explicit
self.some_private_method
end
# self as an implicit receiver (will be ok)
def implicit
some_private_method
end
private
def some_private_method; end
end
Example.new.implicit
Googleトレイルでこの質問を見つけた人へのメッセージ:これは役に立つかもしれません- http://weblog.jamisbuck.org/2007/2/23/method-visibility-in-Ruby
ここに短いものと長いものがあります。 Rubyでプライベートが意味するものは、明示的なレシーバー、たとえばsome_instance.private_method(value)を使用してメソッドを呼び出すことはできません。プライベートメソッドにはアクセスできません。
このように考えると、クラスのインスタンスに割り当てた変数を使用してプライベートメソッドを呼び出すことができると思いますか?いいえ。Selfは変数なので、同じ規則に従う必要があります。ただし、インスタンス内でメソッドを呼び出すだけでは、レシーバーを明示的に宣言していないため、期待どおりに機能します。
Rubyがそのままであるため、instance_evalを使用してプライベートメソッドを実際に呼び出すことができます。
class Foo
private
def bar(value)
puts "value = #{value}"
end
end
f = Foo.new
begin
f.bar("This won't work")
rescue Exception=>e
puts "That didn't work: #{e}"
end
f.instance_eval{ bar("But this does") }
それがもう少し明確であることを願っています。
-編集-
私はあなたがこれがうまくいくと知っていたと仮定しています:
class Foo
def public_m
private_m # Removed self.
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
definition of private
in Rubyは、「明示的な受信者なしでのみ呼び出すことができます」。それが、他の説明はありません。
実際にはルールには例外があることに注意してください。ローカル変数とメソッド呼び出しのあいまいさのため、以下はalwaysがローカル変数への割り当てとして解決されます。
foo = :bar
foo=
というライターを呼び出す場合はどうしますか?さて、あなたはhave明示的なレシーバーを追加します、なぜならレシーバーなしではRubyは単にメソッドfoo=
を呼び出す代わりにローカル変数foo
に割り当てる:
self.foo = :bar
しかし、foo=
というprivate
ライターを呼び出したい場合はどうしますか? できないself.foo =
はfoo=
がprivate
であり、したがって明示的なレシーバーで呼び出すことができないため、書き込みます。さて、実際にはthis特定のケース(およびこのケースalone)の場合、canは実際にself
の明示的なレシーバーを使用してprivate
ライターを呼び出します。
奇妙ですが、Rubyの可視性修飾子に関する多くのことは奇妙です。 self
が暗黙のレシーバーであっても、実際にスペルアウトすると、Rubyランタイム。目に見えて明示的になります。 、それはself
カウントでも意味します。
IIRC、プライベートメソッドではonly暗黙のレシーバー(もちろん、常に自己です)が許可されます。
User Gatesソリューションにいくつかの機能強化を追加します。クラスメソッドまたはインスタンスメソッドにプライベートメソッドを呼び出すことはほとんど可能です。これがコードスニペットです。しかし、お勧めしません。
クラスメソッド
class Example
def public_m
Example.new.send(:private_m)
end
private
def private_m
puts 'Hello'
end
end
e = Example.new.public_m
インスタンスメソッド
class Example
def self.public_m
Example.new.send(:private_m)
end
private
def private_m
puts 'Hello'
end
end
e = Example.public_m
私のprevoiusの回答でごめんなさい。あなたの質問がわかりません。
コードを次のように変更しました。
class Foo
def public_m
private_m # <=
end
def Foo.static_m
puts "static"
end
def self.static2_m
puts "static 2"
end
private
def private_m
puts 'Hello'
end
end
Foo.new.public_m
Foo.static_m
Foo.static2_m
インスタンスメソッドの呼び出しは次のとおりです。
def public_m
private_m # <=
end
クラスメソッドの呼び出しは次のとおりです。
def Foo.static_m
puts "static"
end
def self.static2_m
puts "static 2"
end
Foo.static_m
Foo.static2_m
質問に正確には答えませんが、この方法でプライベートメソッドを呼び出すことができます
class Example
private
def example_test
puts 'Hello'
end
end
e = Example.new
e.send(:example_test)