程式扎記: [ Ruby Gossip ] Basic : 變數、操作與物件 - 變數

標籤

2014年10月14日 星期二

[ Ruby Gossip ] Basic : 變數、操作與物件 - 變數

Source From Here 
Preface 
依型態資訊是記錄在宣告在變數之上,或者是執行時期的物件之上,程式語言可以區分為靜態(Static)語言(例如C/C++、Java)與動態(Dynamic)語言(例如Python、JavaScript)。Ruby是動態語言,也就是變數本身並沒有型態資訊,型態的資訊是在執行時期的物件之上,在 Ruby 中有五種變數,包括 區域變數全域變數實例變數類別變數 與 常數。 

變數 
要建立區域變數,無需宣告型態,只要以小寫字母開頭命名變數並指定值給它,就建立了一個變數,在建立變數之前,嘗試存取某個變數會發生變數未定義的錯誤。例如: 
 

在上例中,一開始建立了一個 x 變數,參考至整數 10,由於變數本身沒有型態,之後你可以將字串"Justin"指定給 x。在 Ruby 中,變數始終是個參考至真實物件的名稱,指定運算只是更改變數的參考對象。例如: 
>> x = 1.0
=> 1.0
>> y = x
=> 1.0
>> x.object_id
=> 3696828
>> y.object_id
=> 3696828 # y 與 x 指向同一個物件, 故 object_id 相同
>> y = 2.0
=> 2.0
>> x.object_id
=> 3696828
>> y.object_id
=> 20871252 # 此時 y 指向不同物件

在上例中,x 一開始參考至 1.0 浮點數物件,而後將 x 參考的物件指定給 y 來參考,你可以使用 object_id 方法來取得所參考物件的記憶體位址代表數字,可以看到 x 與 y 都參考同一物件。之後 y 參考至2.0,所以 x 與 y 就參考至不同的物件。 
>> x = 1
=> 1
>> x.object_id
=> 3
>> x = x + 1
=> 2 
>> x.object_id
=> 5 # 此時 x 指向新的物件, 故 object_id: 3->5

之後+運算後,建立了新的2整數物件,而後指定給 x,所以 x 參考至新的物件。由於變數在Ruby中只是個參考至物件的名稱,所以對於可變動物件,才會有以下的操作結果: 
>> x = [1, 2]
=> [1, 2]
>> x.object_id
=> 2042
>> x[0]=10
=> 10
>> x
=> [10, 2]
>> x.object_id
=> 2042 # 因為 x 指向 array, 即使 array 內容變動, 只要 x 指向同一個 array, object_id 就不變.

在 Ruby 中,== 常單純比較兩個物件的實質內容是否相同。例如: 
>> list1 = [1, 2, 3]
=> [1, 2, 3]
>> list2 = [1, 2, 3]
=> [1, 2, 3]
>> list1 == list2 # == 用來比對 array 內容是否相同
=> true
>> list1.object_id
=> 21564936
>> list2.object_id
=> 21538056
>> list1.equal? list2 # .equals? 比對是否相同物件
=> false

上例中,實際上 list1 與 list2 是參考至不同的物件,如果想知道兩個變數是否參考同一物件,除了使用 object_id 得知之外,通常還可以使用 equal? 方法。 

相等比較還可以使用 eql? 方法,這個方法通常會檢查變數是否參考同一實例,若否則比較物件是否為同一類別的實例,若是則比較實值是否相同。例如: 
>> x = 1.0
=> 1.0
>> y = 1
=> 1
>> x == y
=> true
>> x.eql? y
=> false
>> x.eql? 1.0
=> true

上例中,x 與 y 參考的物件分別是 Float 與 Fixnum 的實例,因此 eql? 比較結果為false。 

相等比較還可以使用===,通常若===兩邊都是實例,預設實作會比較兩個變數是否參考同一實例,如果不是,會再呼叫==。如果左邊是類別而右且是實例,===比較實例是否由該類別所生成。使用case...when...else 時,就是使用 === 作為依據。 

Ruby 區域變數有個特性,直譯器只要看到程式碼中有「變數=值」的語句,就會為建立該變數,這會造成有以下的結果: 
 

在上例中,雖然 if 的區塊不會執行,但直譯器看到 a = 10,就會建立 a 變數,因此之後嘗試顯示 a 的值,是有 a 變數但預設為 nil,然後 b 變數是不存在的,因此出現錯誤。 

在 Ruby 中若要建立全域變數,變數名稱只要以 $ 開頭,全域變數一旦建立,整個程式都是可見。例如: 
- main.rb 
  1. $x = 10  
  2. x = 20  
  3. puts "%d, %d" % [$x, x]  
  4.   
  5. load "util.rb"  
  6.   
  7. puts "%d, %d" % [$x, x]  
- util.rb 
  1. $x = 100  
  2. x = 200  
在上例中,main.rb 中的 $x 是全域變數,x 是區域變數,範圍限於 main.rb 中,util.rb 中的 $x 是全域變數,x 是區域變數,範圍限於 util.rb 中,在 load "util.rb" 執行其內容時,$x 被設定為100,由於是全域變數,這個修改在 main.rb 是可見的,因此第二次 puts 時,會看到 $x 的值為100。 
# ruby main.rb
10, 20
100, 20

在 Ruby 中有一些內建的全域變數,用來儲存整個系統可見的資訊,可查看 Ruby 安裝目錄中的 English.rb,瞭解有哪些全域變數可用。例如: 
>> $$
=> 4656
>> require "English"
=> true
>> $PID
=> 4656

$$ 可以取得目前程式的行程 ID,要求 English 特性之後,可以用較清楚的名稱使用全域變數,例如 $PID 就等於 $$。 

如果變數名稱以大寫作開頭,則稱之為常數,在 Ruby 中,常數並非不能修改,只不過你對常數作第二次修改的話,直譯器會提出警告: 
>> XCONST = 10
=> 10
>> XCONST = 20
(irb):2: warning: already initialized constant XCONST
=> 20

實例變數與類別變數,之後會再說明。

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!