2
w = Widget.new # Create a Widget
w.send :utility_method # Invoke private method!
w.instance_eval { utility_method } # Another way to invoke it
w.instance_eval { @x } # Read instance variable of w

Widget クラス (下記) に関連する上記の例を見ると、send および instance_eval メソッドは、非公開および保護された可視性によって提供されるすべての保護に違反しています。もしそうなら、あなたの定義が尊重されるという保証がないのに、なぜRubyでプライベートで保護されたアクセスに煩わされるのですか?

class Widget
  def x # Accessor method for @x
   @x
  end
  protected :x # Make it protected
  def utility_method # Define a method
   nil
  end
  private :utility_method # And make it private
end
4

5 に答える 5

13

ruby は、あなたがやりたいことをする力をあなたに与えると信じています。誤って足を撃ち落とすのは簡単ではありません.private宣言を覆したい場合は、そうしていることを明確にする構文を使用する必要があります. コードが何をすべきか、何をすべきでないかを最終的に決定するのは、ライブラリを書いている人ではなく、ライブラリを使用している人であることに注意してください。

于 2009-05-22T06:44:59.327 に答える
5

担当者が少ないため、コメントできません:/。

send は、メッセージ送信を実際に実装するメソッドである__send__ (underscore,underscore,"send",underscore,underscore) の単なる共通名であるため、send を再定義しても意味がありません。__method__を再定義することはお勧めしません。さらに、他の人はクラスを再度開いて定義を元に戻すこともできます。

class Widget
  def send(method, *args, &block)
    super
  end
  #and so on
end

Ruby 1.9 では、動作が少し異なります。#send は実際には可視性を尊重しますが、__send__はそうではありません。

Ruby の private には、より宣言的な目的があります。private として宣言されたメソッドは、実装の詳細であり、API の詳細ではありません。誤って外部からメッセージを送信することはできません。しかし、自分のアカウントで、必要に応じて、誰もがその制限を強制的に回避することができます.

于 2009-05-22T12:19:50.743 に答える
1

少なくとも、Widget クラスのパブリック API が何であるかを表現します。

于 2009-05-22T06:41:02.843 に答える
0

持ち帰りのメッセージは次のとおりです。気にしないでください。

Ruby は、Python と同様に、サンドボックス化がまったく苦手です。何かをロックダウンしようとすると、それを回避する方法が常にある可能性があります。Ruby でプライベート属性を取得するさまざまな方法は、私の主張を証明しています。

なんで?彼らはそのように設計されているからです。どちらの言語も、実行時にさまざまな操作ができるように設計されています。クラスを封印することで、Ruby のメタプログラミングが提供する力を他の人から奪うことになります。

Javaにはリフレクションがあります。C++ にはポインターがあります。Haskell にも unsafePerformIO があります。プログラムを保護したい場合は、言語を使用するのではなく、オペレーティング システム レベルで保護する必要があります。

于 2011-12-06T00:12:51.900 に答える