亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

首頁 慕課教程 Ruby 入門教程 Ruby 入門教程 34 動態處理各種類型變量

動態處理各種類型變量

之前的章節中我們學習了 Ruby 中一共有局部、實例、類、全局 4 種變量,以及一種常量,今天讓我們來學習一下在元編程中,如何動態獲取這些變量。

1. 局部變量

局部變量以往我們使用eval來獲取。

實例:

b = binding

(1..3).each do |num|
  b.eval("a_#{num} = #{num}")
end

(1..3).each do |num|
  puts b.eval("a_#{num}")
end

# ---- 輸出結果 ----
1
2
3

Tipsbinding是獲取所處在的作用域的方法。

解釋:因為each后面有一個 block,兩個 block 里面的作用域不共享(詳細在作用域章節中會學習到),這里我們用了binding,讓eval可以共享頂級作用域。分別動態定義了 a_1~a_3 的方法,并動態輸出出來。

在 Ruby 2.1.0 之后,增加了local_variable_set、和local_variable_get方法。

實例:

b = binding

(1..3).each do |num|
  b.local_variable_set("a_#{num}".to_sym, num)
end

(1..3).each do |num|
  puts b.local_variable_get("a_#{num}".to_sym)
end

# ---- 輸出結果 ----
1
2
3

它們本質上是相同的。

2. 實例變量

同樣我們可以使用eval來獲取,只需要在局部變量前加一個@,本著少使用eval的原則,這里我只給大家講解我們更常用的instance_variable_setinstance_variable_get。

實例:

class Person
  def initialize
    (1..3).each do |num|
      instance_variable_set("@name_#{num}".to_sym, num)
    end
  end
   (1..3).each do |num|
     define_method "name_#{num}".to_sym do
       instance_variable_get("@name_#{num}".to_sym)
     end
   end
end

person = Person.new
p person.name_1
p person.name_2
p person.name_3

# ---- 輸出結果 ----
1
2
3

解釋:在類被定義的時候,動態創建3個方法:name_1、name_2name_3,分別返回實例變量@name_1、@name_2@name_3。在類被實例化的時候,動態增加了三個實例變量@name_1,@name_2,@name_3,并賦予1、2、3的初值。

3. 類變量

動態設置類變量所使用到的方法為:class_variable_setclass_variable_get

實例:

class Person
  (1..3).each do |num|
    class_variable_set("@@name_#{num}".to_sym, num * 3)
  end
  
  def initialize
    (1..3).each do |num|
      instance_variable_set("@name_#{num}".to_sym, self.class.class_variable_get("@@name_#{num}".to_sym))
    end
  end
   (1..3).each do |num|
     define_method "name_#{num}".to_sym do
       instance_variable_get("@name_#{num}".to_sym)
     end
   end
end

person = Person.new
p person.name_1
p person.name_2
p person.name_3

# ---- 輸出結果 ----
3
6
9

解釋:這次我們在類初始化的時候創建了@@name_1、@@name_2、@@name_3三個變量賦予3、6、9三個初值。在類實例化的時候使用類變量分別對@name_1@name_2、@name_3進行初始化。注意這里class_variable_get是類方法,所以要使用self.class來獲取。

4. 全局變量

可以使用eval,但是不建議這樣做,因為非常難以調試和維護這些全局變量。

5. 常量

動態操作常量我們使用const_getconst_set兩個方法。

module Test
  (1..3).each do |num|
    const_set "CONSTANT_#{num}", num
  end

  (1..3).each do |num|
    const_set "CONSTANT_#{num}"
  end
end

# ---- 輸出結果 ----
1
2
3

注意事項:const_getconst_set這兩個方法要放在module里面才可以使用。另外不要對常量進行重復賦值。

6. 小結

本章節我們學習了:

  1. 局部變量使用local_variable_setlocal_variable_get;
  2. 實例變量使用instance_variable_setinstance_variable_get;
  3. 類變量使用class_variable_setclass_variable_get;
  4. 常量使用const_setconst_get;
  5. 全局變量不建議動態創建和調用;
  6. 所有動態處理變量都可以使用eval,但是不推薦使用。