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

Ruby 動態調用方法

本章節我們會講解學習如何在 Ruby 中如何動態調用方法。

1. 如何動態調用方法

我們使用send來動態調用方法。

實例:

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


# ---- 輸出結果 ----
"rain"
"hurricane"
"###################"
"rain"
"hurricane"

解釋:

在此示例中,我們定義了一個具有兩個方法的類,然后使用send方法調用了每個方法。為了進行比較,我們還使用點運算符(.)以通常的方式調用了相同的方法。

**注意事項:**方法名的類型通常使用Symbol,字符串也沒有問題。

cloud = Cloud.new
cloud.send(:rain)
cloud.send(:hurricane)
p "====================="
cloud.send("rain")
cloud.send("hurricane")

"rain"
"hurricane"
"rain"
"hurricane"

2. 動態調用方法傳遞參數

2.1 傳遞往常一樣的參數

要使用send將參數發送給方法,我們需要在方法名稱后指定參數。我們可以放多少東西沒有限制。

實例:

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")

# ---- 輸出結果 ----
"Hello!"
"Hi!"
"Hello!"
"Hola!"
["first", "second", "third"]
"keywooord parameter"

我們可以看到,傳遞塊沒有什么區別,在兩種情況下,我們收到的結果都是相同的。

2.2 傳遞一個block

實例:

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!"}


# ---- 輸出結果 ----
"rain"
"It's raining! "
"hurricane"
"Wow! I better stay home today!"
"###################"
"rain"
"It's raining! "
"hurricane"
"Wow! I better stay home today!"

傳遞參數的方式非常明顯,方法調用的結構變化不大。

注意事項:

如果方法名稱指定不正確,我們將看到一個異常。

實例:

class ExampleClass

  def method_name 
  end 

end

instance = ExampleClass.new 
instance.send(:method_method_name)

# ---- 輸出結果 ----
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. 動態調用方法的實例

當我們想一次調用多個方法時,最適合使用send方法。

想象一下,我們擁有一些包含許多不同引擎的技術,我們需要啟動每個引擎。

實例:

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 

我們可以注意到,首先是所有方法名稱中都有一個通用詞“ engine”。第二個問題是,如果方法數量增加,我們將不得不擴展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

# ---- 輸出結果 ---
"lower engine wroom wooom"
"upper engine wroom wroom"
"left upper engine wroooooom"
"right upper engine wroooooom"

這樣我們代碼的擴展性就變得高了。

4. 小結

本章中我們學習了:

  • send方法在Object類中定義作為參數,我們可以傳遞字符串或字符。

  • 我們可以傳遞一個塊,就像通常的方法調用一樣。

  • 我們也可以像往常一樣傳遞所有相同的參數。

  • 如果方法名稱指定不正確,我們將看到一個異常。

  • 當我們動態獲取方法名稱時,此方法非常理想。

  • 當我們想一次調用多個方法時,send方法是合適的。