ルビーでは、ファイル内(またはモジュール内)のすべてのクラスで表示されるが、ファイルを必要とするファイルでは表示されないメソッドを定義する方法はありますか?
関連していますが、まったく同じではありません。この再定義が現在のファイルでのみ表示されるように、メソッド(たとえば、標準ライブラリのクラスのメソッド)を再定義できますか?他のすべてのファイルは、元の定義を表示する必要があります。
ルビーでは、ファイル内(またはモジュール内)のすべてのクラスで表示されるが、ファイルを必要とするファイルでは表示されないメソッドを定義する方法はありますか?
関連していますが、まったく同じではありません。この再定義が現在のファイルでのみ表示されるように、メソッド(たとえば、標準ライブラリのクラスのメソッド)を再定義できますか?他のすべてのファイルは、元の定義を表示する必要があります。
いいえ、いいえ。
Rubyでの唯一の可視性は、パブリック、保護、およびプライベートです。ファイルレベルの可視性の概念はありません。あなたは多分「ごまかして」そしてこのようなことをすることができます:
# In some file foobar.rb
class Foo
def to_bar
Bar.new.file_private
end
end
class Bar
def file_private
raise unless caller[0].split(':')[0] == __FILE__
end
end
# In IRB or some other file
Foo.new.to_bar #=> nil
Bar.new.file_private #=> RuntimeError
しかし、これは悪い考えです。別のディレクトリにある同じ名前のファイルが機能する場合があります。また、これは真の可視性ではなく、メソッド自体に強制されます。
ただし、実際には、ほとんどの場合、クラスをそれぞれ独自のファイルに含める必要があります。それは組織をより良くします。さらに、パブリック/保護/プライベートに依存しないでください。いつでもsend
プライベートメソッドを呼び出すために使用できますが、上記はその期待を破ります。あなたのコードのユーザーが本当にあなたのコードで何かをしたいのなら、彼らにそれをさせることからほとんど何もありません、それは動的言語の性質です。メソッドを文書化しないと、ほとんどのユーザーはそれがとにかくそこにあることさえ知らないでしょう:P
。
2番目の質問については、同じクラスに同じ名前の2つのメソッドを異なる可視性で含める方法はありません。2番目のメソッドは、常に元のメソッドを上書きします。上記と同様のことを行い、条件に応じてレイズする代わりに異なるコードを実行することもできますが、上記のように、これは良い考えではないと思います。
Objectクラス(属性など)で新しいメソッドを定義します。Objectクラスを台無しにしたくない場合は、別の名前を使用できます。Fooはそのクラスを継承する必要があります。
class Object
@@file_only_methods = []
def file_only(method_name)
method_name = method_name.to_sym
new_method_name = "file_only_#{method_name}".to_sym
self.send(:alias_method, new_method_name, method_name)
self.send(:undef_method, method_name)
self.send(:private, new_method_name)
@@file_only_methods << method_name
end
def method_missing(method_name, *arg, &block)
if @@file_only_methods.include? method_name
if __FILE__ == $0
self.send("file_only_#{method_name}".to_sym,*arg,&block)
else
raise "Method #{method_name} is called outside the definition file."
end
else
raise "Method #{method_name} does not exist."
end
end
end
class Foo
def bar
puts 'bar method'
end
file_only :bar
end
Foo.new.bar
#output:bar method
Foo.new.x
#output:no method
file2.rbで、
require_relative 'file1'
Foo.new.bar
#output: Method bar is called outside the definition file.