Ruby中require, require_relative,load,include的用法和區(qū)別

引言

在Ruby中,當(dāng)我們想引用某些庫或者其它文件中定義的類和方法時候,會使用 require 或者require_relative,load,include

那么,它們兩個有什么區(qū)別? Ruby怎么知道要去哪里搜索,也就是,Ruby的require的默認(rèn)搜索路徑是什么?

require

require是Ruby中用的最多的,它通常用來導(dǎo)入系統(tǒng)庫,還有我們用gem安裝的三方庫.我們自己工程中的文件之間的相互引用,也是用的它.

require的用法

require 'commander/import'
require 'terminal-table'
require 'term/ansicolor'
require 'csv'

require 'cupertino'

Ruby會在ruby所對應(yīng)的gem庫的搜索路徑去尋找指定的文件,什么意思呢,就是說,如果你系統(tǒng)上有多個ruby,那么你用的哪個ruby來跑,那么其搜索使用的就是對應(yīng)版本的ruby的gem的搜索庫

ruquire的搜索路徑在全局變量 :(這個全局變量名字就是:,帶冒號的)中,:也等價于LOAD_PATH.

當(dāng)我們在ruby中,想使用另外一個ruby中的內(nèi)容,需要用require關(guān)鍵字來加載另外的ruby文件中的內(nèi)容 require會在預(yù)設(shè)的 :(等價于LOAD_PATH)中去查找對應(yīng)的文件

例如,在我的電腦上,默認(rèn)的全局$:的路徑是

?  testRuby ruby -e 'puts $:'
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/site_ruby/2.6.0
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/site_ruby/2.6.0/x86_64-darwin18
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/site_ruby
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/vendor_ruby/2.6.0
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/vendor_ruby/2.6.0/x86_64-darwin18
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/vendor_ruby
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0
/Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/x86_64-darwin18

可能你會覺得奇怪,上面輸出的路徑似乎并沒有包含我們使用gem install安裝的三方庫.我們用命令輸出下gem的安裝目錄

?   gem env | grep -A2 'GEM PATHS'
  - GEM PATHS:
     - /Users/yohunl/.rvm/gems/ruby-2.6.0
     - /Users/yohunl/.rvm/rubies/ruby-2.6.0/lib/ruby/gems/2.6.0

其實(shí)這是因?yàn)?用戶gem的安裝目錄,是在require執(zhí)行的時候,動態(tài)先添加到$:中去的.
我們可以打開irb來驗(yàn)證一下

old_load_path = $LOAD_PATH.dup
require 'cocoapods'
new_load_path = $LOAD_PATH.dup

從輸出的結(jié)果可以看出來,當(dāng)執(zhí)行了一個require后,$:的結(jié)果增加了很多,差不多增加了20個....

這也就驗(yàn)證了,在第一次執(zhí)行到require的時候,require內(nèi)部會先添加路徑.

目前,require已經(jīng)支持相對路徑了!!!!很多文章中說的不支持,已經(jīng)是過去式了.

例如 在我們目錄下下有兩個文件 a.rb 和b.rb

.
├── a.rb
└── b.rb

由于require的搜索路徑并沒有當(dāng)前目錄,所以直接 require "b"是不行的.

有以下幾種方式:

require "./b" #采用相對路徑

或者

$: << File.dirname(__FILE__)
require "b"

或者

$LOAD_PATH.push File.dirname(__FILE__)
require "b"

或者

$LOAD_PATH.unshift(File.dirname(__FILE__)) unless $LOAD_PATH.include?(File.dirname(__FILE__))  

require "b"

或者

require File.dirname(__FILE__) + '/b.rb'

或者

require File.expand_path('../b.rb', __FILE__)

那么,如果我們想包含一個文件夾下有所的文件呢?
最好的方法是將目錄添加到加載路徑,然后require每個文件的基本名稱.當(dāng)然你也可以用如下的命令來加載文件夾下所有的文件

Dir["/path/to/directory/*.rb"].each {|file| require file }

另外,有人寫了一個簡單的require_all來實(shí)現(xiàn)這個功能,可以用

gem install require_all

來安裝它

require_relative

require_relative的調(diào)用是相對路徑。如當(dāng)前文件夾下存在一個名為foo.rb的文件時氧吐,調(diào)用的方式為require_relative 'foo'盏袄。它不能調(diào)用$LOAD_PATH中的包

load

load也是加載一個文件仪媒,它與require_relative的區(qū)別是:

require_relative多次加載同一文件時戚啥,只會加載一次祠斧;load每一次調(diào)用都會重加載該文件吞琐。

include

我們平時用的很少
Ruby Require VS Load VS Include VS Extend 有詳細(xì)的介紹,這里摘錄關(guān)鍵的部分

在一個模塊中,可能會有很多膠水代碼,也就是說類A中有一些函數(shù),和類B中一些函數(shù)的實(shí)現(xiàn)是 一模一樣的,這個時候,就可以把 那部分一樣的函數(shù)提取出來,寫在module中,然后在每個類用include這個module
就很簡便在這個類中插入了module中的這幾個方法了,避免了拷貝型的重復(fù)工作

module Log 
  def class_type
    "This class is of type: #{self.class}"
  end
end

class TestClass 
  include Log 
end

tc = TestClass.new.class_type
puts tc #This class is of type: TestClass
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末砂轻,一起剝皮案震驚了整個濱河市奔誓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌搔涝,老刑警劉巖厨喂,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異庄呈,居然都是意外死亡蜕煌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進(jìn)店門诬留,熙熙樓的掌柜王于貴愁眉苦臉地迎上來斜纪,“玉大人,你說我怎么就攤上這事故响】悖” “怎么了?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵彩届,是天一觀的道長伪冰。 經(jīng)常有香客問我,道長樟蠕,這世上最難降的妖魔是什么贮聂? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮寨辩,結(jié)果婚禮上吓懈,老公的妹妹穿的比我還像新娘。我一直安慰自己靡狞,他們只是感情好耻警,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著甸怕,像睡著了一般甘穿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梢杭,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天温兼,我揣著相機(jī)與錄音,去河邊找鬼武契。 笑死募判,一個胖子當(dāng)著我的面吹牛荡含,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播届垫,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼释液,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了敦腔?” 一聲冷哼從身側(cè)響起均澳,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎符衔,沒想到半個月后找前,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡判族,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年躺盛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片形帮。...
    茶點(diǎn)故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡槽惫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辩撑,到底是詐尸還是另有隱情界斜,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布合冀,位于F島的核電站各薇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏君躺。R本人自食惡果不足惜峭判,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望棕叫。 院中可真熱鬧林螃,春花似錦、人聲如沸俺泣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伏钠。三九已至横漏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贝润,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工铝宵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留打掘,地道東北人华畏。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像尊蚁,于是被迫代替她去往敵國和親亡笑。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評論 2 355

推薦閱讀更多精彩內(nèi)容