ruby的load與require是差在什麼地方?
2016-05-02 14:58:30

Load

首先我們先建立三個檔案a.rb, b.rb, c.rb如下:

a.rb
A = "A constant in a.rb"
p "Print A = '#{A}' in a.rb"
b.rb
A = "A constant in b.rb"
p "Print A = '#{A}' in b.rb"

如果在c.rb裡同時load a.rb與b.rb兩個檔案:

c.rb
load("a.rb")
load("b.rb")
p "Print A = '#{A}' in c.rb"
load("b.rb")

則會出現下面的結果:

"Print A = 'A constant in file a.rb' in a.rb"
b.rb:1: warning: already initialized constant A
a.rb:1: warning: previous definition of A was here
"Print A = 'A constant in file b.rb' in b.rb"
"Print A = 'A constant in file b.rb' in c.rb"
b.rb:1: warning: already initialized constant A
b.rb:1: warning: previous definition of A was here
"Print A = 'A constant in file b.rb' in b.rb"

由此可知,使用load有下面特性:

  • 被load的檔案會被執行(print有被執行)。
  • 如果load的兩個檔案裡有相同的constant,則會出現警告,而且會以最後載入的constant為主。
  • 如果重複load相同的檔案,則檔案會被重複執行。

如果不想將b.rb裡的constant載入到c.rb中,則可以在load後面加上true:

c.rb
load("a.rb")
load("b.rb", true)
p "Print A = '#{A}' in c.rb"
"Print A = 'A constant in file a.rb' in a.rb"
"Print A = 'A constant in file b.rb' in b.rb"
"Print A = 'A constant in file a.rb' in c.rb"

上面執行的結果就只會讀到a.rb的A,但b.rb的程式碼仍會執行。

Require

如果將c.rb改成require如下:

require("./a")
require("./b")
p "Print A = '#{A}' in c.rb"
require("./b")

則結果會變成:

"Print A = 'A constant in file a.rb' in a.rb"
/Users/kait/temp/b.rb:1: warning: already initialized constant A
/Users/kait/temp/a.rb:1: warning: previous definition of A was here
"Print A = 'A constant in file b.rb' in b.rb"
"Print A = 'A constant in file b.rb' in c.rb"

由此可知,require與load的差別在於

  • require需要指定絕對路徑(更精確來說,如果不指定絕對路徑,則預設會去找$LOAD_PATH目錄裡有沒有指定的檔案,範例是將a.rb, b.rb, c.rb放在同一個目錄下,而./並不在預設的$LOAD_PATH,所以不加./會找不到)
  • require可以省略檔案的副檔名.rb,但load則是一定要加.rb,不然會找不到檔案。
  • 如果require兩次相同的檔案,則檔案只會載入並執行第一次,之後的不會重複載入執行,load則每次都會載入執行。