3

ルビーでは、ファイル内(またはモジュール内)のすべてのクラスで表示されるが、ファイルを必要とするファイルでは表示されないメソッドを定義する方法はありますか?

関連していますが、まったく同じではありません。この再定義が現在のファイルでのみ表示されるように、メソッド(たとえば、標準ライブラリのクラスのメソッド)を再定義できますか?他のすべてのファイルは、元の定義を表示する必要があります。

4

2 に答える 2

8

いいえ、いいえ。

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番目のメソッドは、常に元のメソッドを上書きします。上記と同様のことを行い、条件に応じてレイズする代わりに異なるコードを実行することもできますが、上記のように、これは良い考えではないと思います。

于 2012-05-10T14:11:18.340 に答える
1
  1. 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.
    
于 2012-05-10T14:14:05.560 に答える