从文件中包含模块

到目前为止,我已经混入了在单个源文件中定义的模块。通常,在单独的文件中定义模块并根据需要将它们混入更有用。要使用其它文件中的代码,你必须要做的第一件事是使用 require 方法加载该文件,如下所示:

  1. require( "testmod.rb" )

(可选)你可以省略文件扩展名:

  1. require( "testmod" ) # this works too

所需文件必须位于当前目录,搜索路径或预定义数组变量 $: 中列出的文件夹中。你可以使用常用的 array-append 方法 << 向此数组变量添加元素,以这种方式:

  1. $: << "C:/mydir"
全局变量 $:(美元符号和冒号)包含一个字符串数组,表示 Ruby 在查找加载或引入文件时搜索的目录。

如果成功加载指定的文件,require 方法返回 true 值;否则返回 false。如果有疑问,你只需显示结果:

  1. puts(require( "testmod.rb" ))

当需要该文件时,将执行在文件运行时通常执行的任意代码。因此,如果文件 testmod.rb 包含此代码…

testmod.rb
  1. def sing
  2. puts( "Tra-la-la-la-la....")
  3. end
  4. puts( "module loaded")
  5. sing

…文件 require_module.rb 包含它…

require_module.rb
  1. require( "testmod.rb")

…然后,当运行 require_module.rb 时,这将输出:

  1. module loaded
  2. Tra-la-la-la-la....

在所需文件中声明的模块,可以将其混入:

  1. require( "testmod.rb")
  2. include MyModule #mix in MyModule declared in testmod.rb
load_module.rb

Ruby 还允许你使用 load 方法加载文件。在大多数情况下,requireload 可视为可互换的。但是有一些微妙的差异。特别是,load 可以使用可选的第二个参数,如果为 true,则加载并执行代码作为未命名或匿名模块:

  1. load( "testmod.rb", true)

加载的文件不会将新命名空间(namespace)引入主程序,你将无法访问已加载文件中的所有模块。当 load 的第二个参数为 false 或没有第二个参数时,你将可以访问已加载文件中的模块。请注意,使用 load 时你必须输入完整的文件名(”testmod” 减去 “.rb” 扩展名是不行的)。

另一个区别是 require 仅加载一次文件(即使你的代码多次引入该文件),而 load 会导致每次调用 load 时重新加载指定的文件。我们假设你在文件 test.rb 中有这个:

test.rb
  1. MyConst = 1
  2. if @a == nil then
  3. @a = 1
  4. else
  5. @a += MyConst
  6. end
  7. puts @a

我们假设你现在引入(require)这个文件三次:

require_again.rb
  1. require "test"
  2. require "test"
  3. require "test"

这里将会输出:

  1. 1

但是如果你加载(load)文件三次…

load_again.rb
  1. load "test.rb"
  2. load "test.rb"
  3. load "test.rb"

…那么这将会输出:

  1. 1
  2. ./test.rb:1: warning: already initialized constant MyConst
  3. 2
  4. ./test.rb:1: warning: already initialized constant MyConst
  5. 3