1. 程式人生 > >有趣的Ruby-學習筆記4

有趣的Ruby-學習筆記4

all 庫文件 scrip 。。 trac module 由於 content pos

Ruby塊

塊。在我看來就是插入一段可變的函數
block_name{
   statement1
   statement2
   ..........
}

看起來不知道是什麽,只是別急,繼續往下看。塊函數通過yield來調用

yield 語句

yield英文就是 屈服。放棄,不知道為什麽用這個單詞。難道是 此處函數就放棄了控制權?樣例
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-

def test
   puts "在 test 方法內"
   yield
   puts "你又回到了 test 方法內"
   yield
end
test {puts "你在塊內"}
運行了這段後的效果是
在 test 方法內
你在塊內
你又回到了 test 方法內
你在塊內
在yield的部分運行了你調用時傳入的塊語句。

所以yield是不是看起來沒啥用?繼續往下看

yield能夠帶參數

您也能夠傳遞帶有參數的 yield 語句。下面是一個實例:
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-

def test
   yield 5
   puts "在 test 方法內"
   yield 100
end
test {|i| puts "你在塊 #{i} 內"}

塊和方法

假設方法的最後一個參數前帶有 &,那麽您能夠向該方法傳遞一個塊,且這個塊可被賦給最後一個參數。假設 * 和 & 同一時候出如今參數列表中,& 應放在後面。
#!/usr/bin/ruby

def test(&block)
   block.call
end
test { puts "Hello World!"}
是不是令你想起了javascript裏面的回調函數?結合上yield傳參,能夠實現傳入一段回調函數,並且該回調函數中能夠依據函數運行的過程中傳入的不同參數做出不同的行為。總算感覺塊這個特性有點用了。。


BEGIN 和 END 塊

BEGIN和END塊就像java中的攔截器,一個是before攔截器。一個是after攔截器
#!/usr/bin/ruby

BEGIN { 
  # BEGIN 代碼塊
  puts "BEGIN 代碼塊"
} 

END { 
  # END 代碼塊
  puts "END 代碼塊"
}
  # MAIN 代碼塊
puts "MAIN 代碼塊"
一個程序能夠包括多個 BEGIN 和 END 塊。BEGIN 塊依照它們出現的順序運行。END 塊依照它們出現的相反順序運行。

當運行時,上面的程序產生產生下面結果:

BEGIN 代碼塊
MAIN 代碼塊
END 代碼塊

Ruby模塊

模塊(Module)是一種把方法、類和常量組合在一起的方式。模塊(Module)為您提供了兩大優點
  • 模塊提供了一個命名空間和避免名字沖突
  • 模塊實現了 mixin 裝置
模塊(Module)定義了一個命名空間,相當於一個沙盒,在裏邊您的方法和常量不會與其它地方的方法常量沖突。


  • 模塊相似與類,但有一下不同模塊不能實例化
  • 模塊沒有子類
  • 模塊僅僅能被還有一個模塊定義
module Identifier
   statement1
   statement2
   ...........
end
模塊常量命名與類常量命名相似,以大寫字母開頭。方法定義看起來也相似:模塊方法定義與類方法定義相似。
樣例

#!/usr/bin/ruby

# 定義在 trig.rb 文件裏的模塊

module Trig
   PI = 3.141592654
   def Trig.sin(x)
   # ..
   end
   def Trig.cos(x)
   # ..
   end
end

require 語句

最終看到require語句了。沒有require功能簡直是不能寫代碼啊,所以結合上require,module功能是我看到最重要的功能了實例
$LOAD_PATH << ‘.‘

require ‘trig.rb‘

y = Trig.sin(Trig::PI/4)
註意這句話 $LOAD_PATH << ‘.‘ 這句話是把require的路徑定到當前的文件路徑,我剛開始require總是失敗就是由於沒有這句話假設不想用 $LOAD_PATH 還能夠使用 require_relative 方法
require_relative ‘trig.rb‘

y = Trig.sin(Trig::PI/4)

也能夠!並且我更喜歡 require_relative 由於更好記

include 語句

您能夠在類中嵌入模塊。

你肯定跟我會有一樣的疑問:“但是,我都有require了為什麽還要include?!”

假設下面代碼寫在 support.rb 裏面

module Week
   FIRST_DAY = "Sunday"
   def Week.weeks_in_month
      puts "You have four weeks in a month"
   end
   def Week.weeks_in_year
      puts "You have 52 weeks in a year"
   end
end

我們來嵌入一下
#!/usr/bin/ruby
$LOAD_PATH << ‘.‘
require "support"

class Decade
include Week
   no_of_yrs=10
   def no_of_months
      puts Week::FIRST_DAY
      number=10*12
      puts number
   end
end
d1=Decade.new
puts Week::FIRST_DAY
Week.weeks_in_month
Week.weeks_in_year
d1.no_of_months
你會發現,有沒有那行 include Week 代碼運行結果根本就沒有差別!

那include有什麽卵用呢?!

要解釋include到底有什麽用,就要介紹一下 ruby 的 mixins 特性

Ruby 中的 Mixins

Ruby中並沒有多重繼承,取而代之的是Mixin。當你將模塊include到類定義中。模塊中的方法就被mix到了類裏面實例代碼,看A, B 怎樣被mix到 Sample裏面
module A
   def a1
   end
   def a2
   end
end
module B
   def b1
   end
   def b2
   end
end

class Sample
include A
include B
   def s1
   end
end

samp=Sample.new
samp.a1
samp.a2
samp.b1
samp.b2
samp.s1

include & require & load


原來include跟require有下面的差別(這邊還要提到load方法)
  • require不須要跟上後綴,會自己主動識別 xxx.rb
  • require假設調用2次就會報錯,假設要調用多次就用load,但是用load得寫上文件後綴名
  • require一般用於載入庫文件,load一般用戶載入配置文件
  • include 用於把一個文件裏的模塊mix到類中
  • include並不會把module的實例方法復制到類中,僅僅是做了引用,包括module的不同類都指向了同一個對象。假設你改變了module的定義。即使你的程序還在運行,全部包括module的類都會改變行為

有趣的Ruby-學習筆記4