如何在模块中扩展Ruby类?

时间:2014-08-11 19:07:34

标签: ruby oop

我试图在模块中扩展File类。这是我的(缩写)代码:

module Wireshark

   # Extend the file class to write a header comment
   class File
     def write_header
        self.puts '/* ' + Wireshark::AUTOGEN_LABEL + ' */'
        self.puts '/* ' + Wireshark::timestamp + ' */'
     end
   end

   # Read a file
   def read
     begin
        file = File.read 'file'
     rescue IOError
        STDERR.puts 'Error reading file.'
        return
     end
   end
end

当我运行我的代码时,我正在

undefined method `read' for Wireshark::File:Class (NoMethodError)

当我尝试运行file.read时。我试图摆脱模块封装,但我只想扩展模块中的File类,而不是我程序的其余部分。

2 个答案:

答案 0 :(得分:1)

你关闭了。

module Wireshark
   module File
     def write_header
        self.puts '/* ' + Wireshark::AUTOGEN_LABEL + ' */'
        self.puts '/* ' + Wireshark::timestamp + ' */'
     end
   end

   # Extend File with the methods in the Wireshark::File module
   ::File.send :include, Wireshark::File

   # Read a file
   def read
     begin
        file = ::File.read 'file'
     rescue IOError
        STDERR.puts 'Error reading file.'
        return
     end
   end
end

这里的一般想法是我们定义一个Wireshark::File模块,它包含你想要包含在File类中的方法,然后你可以直接将它们包含在File中。

您还会注意到,在read方法中,我将File更改为::File。 Ruby将在树上向上试图找到给定常量的最近匹配值,因此,由于您位于Wireshark模块中,并且该范围中有一个名为File的常量,因此只使用{ {1}}获取File。指定Wireshark::File表示"顶级命名空间中的::File常量"。

答案 1 :(得分:0)

在当前版本的Ruby中,不可能这样做,但它是一个受欢迎的proposed extension called "refinements"

如果需要修补核心File类,则需要将其作为猴子补丁进行修补,这会影响Ruby进程中任何位置File的所有实例。

通常你可以这样做:

# Define the instance methods you want to overide
module MyFileHacksInstanceMethods
  def read
    # ... (reimplementation) ...
  end
end

# Force load these in the File class
class File
  include MyFileHacksInstanceMethods
end

您在此示例中声明的是一个名为Wireshark::File的独立类,因为它位于该模块的命名空间内。 ::File是主类(::是强制绝对名称的前缀,类似于文件系统的/