動態(tài)處理各種類型變量
之前的章節(jié)中我們學(xué)習(xí)了 Ruby 中一共有局部、實例、類、全局 4 種變量,以及一種常量,今天讓我們來學(xué)習(xí)一下在元編程中,如何動態(tài)獲取這些變量。
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
# ---- 輸出結(jié)果 ----
1
2
3
Tips:
binding是獲取所處在的作用域的方法。
解釋:因為each后面有一個 block,兩個 block 里面的作用域不共享(詳細(xì)在作用域章節(jié)中會學(xué)習(xí)到),這里我們用了binding,讓eval可以共享頂級作用域。分別動態(tài)定義了 a_1~a_3 的方法,并動態(tài)輸出出來。
在 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
# ---- 輸出結(jié)果 ----
1
2
3
它們本質(zhì)上是相同的。
2. 實例變量
同樣我們可以使用eval來獲取,只需要在局部變量前加一個@,本著少使用eval的原則,這里我只給大家講解我們更常用的instance_variable_set和instance_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
# ---- 輸出結(jié)果 ----
1
2
3
解釋:在類被定義的時候,動態(tài)創(chuàng)建3個方法:name_1、name_2、name_3,分別返回實例變量@name_1、@name_2、@name_3。在類被實例化的時候,動態(tài)增加了三個實例變量@name_1,@name_2,@name_3,并賦予1、2、3的初值。
3. 類變量
動態(tài)設(shè)置類變量所使用到的方法為:class_variable_set和class_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
# ---- 輸出結(jié)果 ----
3
6
9
解釋:這次我們在類初始化的時候創(chuàng)建了@@name_1、@@name_2、@@name_3三個變量賦予3、6、9三個初值。在類實例化的時候使用類變量分別對@name_1、@name_2、@name_3進行初始化。注意這里class_variable_get是類方法,所以要使用self.class來獲取。
4. 全局變量
可以使用eval,但是不建議這樣做,因為非常難以調(diào)試和維護這些全局變量。
5. 常量
動態(tài)操作常量我們使用const_get和const_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
# ---- 輸出結(jié)果 ----
1
2
3
注意事項:const_get和const_set這兩個方法要放在module里面才可以使用。另外不要對常量進行重復(fù)賦值。
6. 小結(jié)
本章節(jié)我們學(xué)習(xí)了:
- 局部變量使用
local_variable_set和local_variable_get; - 實例變量使用
instance_variable_set和instance_variable_get; - 類變量使用
class_variable_set和class_variable_get; - 常量使用
const_set和const_get; - 全局變量不建議動態(tài)創(chuàng)建和調(diào)用;
- 所有動態(tài)處理變量都可以使用
eval,但是不推薦使用。
杜驍 ·
2025 imooc.com All Rights Reserved |