Ruby 動(dòng)態(tài)調(diào)用方法
本章節(jié)我們會(huì)講解學(xué)習(xí)如何在 Ruby 中如何動(dòng)態(tài)調(diào)用方法。
1. 如何動(dòng)態(tài)調(diào)用方法
我們使用send
來動(dòng)態(tài)調(diào)用方法。
實(shí)例:
class Cloud
def rain
p "rain"
end
def hurricane
p "hurricane"
end
end
cloud = Cloud.new
cloud.send(:rain)
cloud.send(:hurricane)
p "====================="
cloud.rain
cloud.hurricane
# ---- 輸出結(jié)果 ----
"rain"
"hurricane"
"###################"
"rain"
"hurricane"
解釋:
在此示例中,我們定義了一個(gè)具有兩個(gè)方法的類,然后使用send
方法調(diào)用了每個(gè)方法。為了進(jìn)行比較,我們還使用點(diǎn)運(yùn)算符(.
)以通常的方式調(diào)用了相同的方法。
**注意事項(xiàng):**方法名的類型通常使用Symbol
,字符串也沒有問題。
cloud = Cloud.new
cloud.send(:rain)
cloud.send(:hurricane)
p "====================="
cloud.send("rain")
cloud.send("hurricane")
"rain"
"hurricane"
"rain"
"hurricane"
2. 動(dòng)態(tài)調(diào)用方法傳遞參數(shù)
2.1 傳遞往常一樣的參數(shù)
要使用send
將參數(shù)發(fā)送給方法,我們需要在方法名稱后指定參數(shù)。我們可以放多少東西沒有限制。
實(shí)例:
class ParametersTest
def method_with_positional_parameter(a)
p a
end
def method_with_few_positional_parameters(a,b,c)
p a,b,c
end
def method_with_infinity_args(*a)
p a
end
def method_with_keyword_parameter(keyword_parameter:)
p keyword_parameter
end
end
test = ParametersTest.new
test.send(:method_with_positional_parameter, "Hello!")
test.send(:method_with_few_positional_parameters, "Hi!", "Hello!", "Hola!")
test.send(:method_with_infinity_args, "first", "second", "third")
test.send(:method_with_keyword_parameter, keyword_parameter: "keywooord parameter")
# ---- 輸出結(jié)果 ----
"Hello!"
"Hi!"
"Hello!"
"Hola!"
["first", "second", "third"]
"keywooord parameter"
我們可以看到,傳遞塊沒有什么區(qū)別,在兩種情況下,我們收到的結(jié)果都是相同的。
2.2 傳遞一個(gè)block
實(shí)例:
class Cloud
def rain
p "rain"
yield
end
def hurricane
p "hurricane"
yield
end
end
cloud = Cloud.new
cloud.send(:rain) { p "It's raining! "}
cloud.send(:hurricane) { p "Wow! I better stay home today!"}
p "###################"
cloud.rain { p "It's raining! "}
cloud.hurricane { p "Wow! I better stay home today!"}
# ---- 輸出結(jié)果 ----
"rain"
"It's raining! "
"hurricane"
"Wow! I better stay home today!"
"###################"
"rain"
"It's raining! "
"hurricane"
"Wow! I better stay home today!"
傳遞參數(shù)的方式非常明顯,方法調(diào)用的結(jié)構(gòu)變化不大。
注意事項(xiàng):
如果方法名稱指定不正確,我們將看到一個(gè)異常。
實(shí)例:
class ExampleClass
def method_name
end
end
instance = ExampleClass.new
instance.send(:method_method_name)
# ---- 輸出結(jié)果 ----
NoMethodError: undefined method `method_method_name' for #<ExampleClass:0x0000000194ff10>
Did you mean? method_name
from (irb):34
from /usr/bin/irb:11:in `<main>'
3. 動(dòng)態(tài)調(diào)用方法的實(shí)例
當(dāng)我們想一次調(diào)用多個(gè)方法時(shí),最適合使用send
方法。
想象一下,我們擁有一些包含許多不同引擎的技術(shù),我們需要啟動(dòng)每個(gè)引擎。
實(shí)例:
class SomeTechnology
def turn_on
lower_engine
upper_engine
left_upper_engine
right_upper_engine
end
private
def lower_engine
p "lower engine wroom wooom"
end
def upper_engine
p "upper engine wroom wroom"
end
def left_upper_engine
p "left upper engine wroooooom"
end
def right_upper_engine
p "right upper engine wroooooom"
end
end
我們可以注意到,首先是所有方法名稱中都有一個(gè)通用詞“ engine”。第二個(gè)問題是,如果方法數(shù)量增加,我們將不得不擴(kuò)展turn_on
方法。
class SomeTechnology
ENGINES = [:lower, :upper, :left_upper, :right_upper]
def turn_on
ENGINES.each do |name|
send("#{name}_engine")
end
end
private
def lower_engine
p "lower engine wroom wooom"
end
def upper_engine
p "upper engine wroom wroom"
end
def left_upper_engine
p "left upper engine wroooooom"
end
def right_upper_engine
p "right upper engine wroooooom"
end
end
tech = SomeTechnology.new
tech.turn_on
# ---- 輸出結(jié)果 ---
"lower engine wroom wooom"
"upper engine wroom wroom"
"left upper engine wroooooom"
"right upper engine wroooooom"
這樣我們代碼的擴(kuò)展性就變得高了。
4. 小結(jié)
本章中我們學(xué)習(xí)了:
-
send
方法在Object
類中定義作為參數(shù),我們可以傳遞字符串或字符。 -
我們可以傳遞一個(gè)塊,就像通常的方法調(diào)用一樣。
-
我們也可以像往常一樣傳遞所有相同的參數(shù)。
-
如果方法名稱指定不正確,我們將看到一個(gè)異常。
-
當(dāng)我們動(dòng)態(tài)獲取方法名稱時(shí),此方法非常理想。
-
當(dāng)我們想一次調(diào)用多個(gè)方法時(shí),
send
方法是合適的。