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

似乎实例方法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都存在两次,作为私有实例方法和公共类方法(也称为单例方法)。

基于这个答案,我想出了这段代码,它基本上将所有类方法从复制FileUtilsFileManager

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 回答
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 回答