2

FileUtilsクラスの機能を拡張するモジュールを作成しようとしています。

require 'fileutils'

module FileManager
  extend FileUtils
end

puts FileManager.pwd

これを実行すると、private method 'pwd' called for FileManager:Module (NoMethodError) エラーが発生します

更新:
これらのクラスメソッドがプライベートに含まれているのはなぜですか?FileManagerモジュールにパブリッククラスメソッドとして各メソッドを手動で含めることなく、すべてを公開するにはどうすればよいですか?

4

2 に答える 2

2
require 'fileutils'

module FileManager
  extend FileUtils

  def FMpwd
    pwd 
  end 

  module_function :FMpwd
end

puts FileManager.FMpwd

=> /home/rjuneja/Programs/stackoverflow

これは、Rubyがプライベートメソッドと保護されたメソッドを他の言語とは少し異なる方法で処理するためです。メソッドがRubyでプライベートとして宣言されている場合、このメソッドを明示的なレシーバーで呼び出すことはできないことを意味します。暗黙のレシーバーを使用してプライベートメソッドを呼び出すことができるときはいつでも、それは常に成功します。あなたはここでより多くの情報を見つけることができます:

http://www.skorks.com/2010/04/ruby-access-control-are-private-and-protected-methods-only-a-guideline/

FileUtilsにモンキーパッチを適用して、代わりに必要なメソッドを含めてみませんか。

require 'fileutils'

module FileUtils
  class << self
    def sayHello
      puts "Hello World!"
    end 
  end 
end

FileUtils.sayHello
=> "Hello World!"
于 2012-10-24T22:43:55.797 に答える
2

上のインスタンスメソッドFileUtilsはすべてプライベートのようです(ここでの別の回答で述べられているように、明示的なレシーバーなしでのみ呼び出すことができます)。そして、インクルードまたはエクステンドしたときに得られるのは、インスタンスメソッドです。例えば:

require 'fileutils'

class A
  include FileUtils
end
A.new.pwd #=> NoMethodError: private method `pwd' called for #<A:0x0000000150e5a0>

o = Object.new
o.extend FileUtils
o.pwd #=> NoMethodError: private method `pwd' called for #<Object:0x00000001514068>

FileUtilsプライベートインスタンスメソッドとパブリッククラスメソッド(別名シングルトンメソッド)として、必要なすべてのメソッドが2回存在することがわかります。

この回答に基づいて、基本的にすべてのクラスメソッドをからFileUtilsにコピーするこのコードを思いつきましたFileManager

require 'fileutils'

module FileManager
  class << self
    FileUtils.singleton_methods.each do |m|
      define_method m, FileUtils.method(m).to_proc
    end
  end
end

FileManager.pwd #=> "/home/scott"

それはきれいではありませんが、それは仕事をします(私が知る限り)。

于 2012-10-24T23:06:33.137 に答える