首页 > 服务端语言 > Ruby 入门教程 > 31 Ruby 动态调用方法

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方法是合适的。

本文来自互联网用户投稿,不拥有所有权,该文观点仅代表作者本人,不代表本站立场。
访问者可将本网站提供的内容或服务用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯本网站及相关权利人的合法权利。
本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站,邮箱:80764001@qq.com,予以删除。
© 2023 PV138 · 站点地图 · 免责声明 · 联系我们 · 问题反馈