【问题标题】:Ruby: What is the best way to interact with a method that accepts multiple arguments?Ruby:与接受多个参数的方法交互的最佳方式是什么?
【发布时间】:2018-12-23 11:46:51
【问题描述】:

可能是重复的,但我搜索了 SO 和 Google,但找不到答案,即使它应该是微不足道的..

一个 Ruby 方法需要多个参数..

def initialize(options = {})
  requires!(options, :arg1, :arg2, ...)
  super
end

如果事先不知道这些必需的参数,如何使用可变数量的参数调用这种方法?

我已经知道 Ruby 1.9.2 和更高版本,我们可以在方法上使用 parameters 方法来获取该方法的参数列表,从那里我可以想象我们可以重用它来调用该方法,因为我们知道它的参数。对吗?

如果不正确,与采用可变数量必需参数的此类方法进行交互的最佳方式是什么?

【问题讨论】:

标签: ruby variables methods arguments


【解决方案1】:

据我了解,您不想提供散列作为参数,而是提供一个值数组,跳过键名。

如果您使用的是第三方库,并且该方法在那里定义 - 这是不可能的,因为该方法旨在接收指定形式的参数(在您的示例中,哈希必须有一些特定的键),并且 Ruby不提供任何了解用户想法的能力(如果您想走极端,您当然可以编写一个源文件解析器来提取来自该哈希的参数)。

如果你自己设计方法,你可以:

def initialize(arguments = {}) 
  case arguments
  when Hash
    @foo = arguments[:foo]
    @bar = arguments[:bar]
  when Array
    @foo = arguments[0]
    @foo = arguments[1]
  else
    raise ArgumentError.new("argument of type Hash or Array expected")
  end
end

【讨论】:

    【解决方案2】:

    我认为该方法不应该关心传入的参数。它应该关心的是它做任何事情所必需的参数。

    这样,您可以让 initialize 方法从与它相关的哈希中获取键,而不必真正担心其他的。

    class Person
      def inititialize(opts: {})
        @name = opts[:person_name] # could be nil
      end
    end
    
    class Car
      def initialize(opts: {})
        @brand = opts[:car_brand] # could be nil
      end
    end
    
    opts = { person_name: "Ivan", car_brand: "Fiat", something_else: "ignored" }
    
    c = Car.new(opts) # is unaware of what is in 'opts'
    #<Car:0xd34db33f>
    p = Person.new(opts) # is unaware of what is in 'opts'
    #<Person:0x1337b347>
    

    我认为封装作为一个原则涵盖了这一点。方法应该只知道它们需要知道的功能。范围不应针对来自其环境的数据进行立法。

    如果您牢记这一点,您可以将任何内容传递给该方法,并允许该方法按照自己的意愿行事。

    【讨论】:

    • 我从来没有提到过这个方法。我问的是调用一个采用可变参数的方法。在您的示例中,我可以在不知道哈希中 keys 名称的情况下传递 opt = {"Ivan", "Fiat"} 吗?我认为封装确实涵盖了这一点,所以感谢您指出我正确的方向。
    • 你能看看这个stackoverflow.com/questions/48220723/… 并告诉我如何初始化网关实例,只传递网关初始化方法所采用的参数键的值吗?
    【解决方案3】:

    您的问题基本上等同于“我怎么知道我不知道的事情”。

    这个问题的答案,坦率地说,就是去了解它。在编程和如何调用方法的上下文中,同样的逻辑适用,这是文档的唯一目的,也是您学习编写 Ruby 代码的方式。我相信您和我们这里的所有人一样,花费了大量时间查看文档,了解如何编写代码、我们可以使用哪些方法、它们的用途、如何调用它们等等。

    如果你遇到了一个函数的存在,而你最初所能知道的只是它接受可变数量的参数,那么你需要弄清楚它。这通常意味着查找它的文档,或者如果您可以访问源代码,请检查方法主体并查看您是否可以确定它的使用方式。

    这就是为什么好的文档是必不可少的,对于那些实际上看不到方法主体和/或其签名的编译语言来说更是如此。如果不存在文档,那么恕我直言,这是废话,您不应该使用它。这就像用自己编造的词汇写一本书,并期望人们必须尝试破译每个单词才能阅读它。你可以写出最美的一段代码,不解释怎么用,公开又有什么意义?

    简单地说,如果您不了解某个方法或它的作用,那么您不应该与它“交互”,至少如果您关心您的代码是否健壮的话。你应该如何调试你甚至不理解的代码?没有可调用的explain_how_to_use_this(method) 函数,您将不得不对其进行研究并进行一些老式的学习。

    【讨论】:

    • 为什么你认为 Ruby 引入了parameters 方法?该方法确实解决了我的问题,但我问的是除此之外的最佳方法!
    • 根据 Ruby 官方文档ruby-doc.org/core-2.2.2/Method.html#method-i-parameters 我应该能够使用parameters 方法来初始化active_merchant 中的网关。现在需要“active_merchant” ActiveMerchant::Billing::Base::gateway( :trust_commerce ).parameters 应该给我类似“login”的东西(这解决了我的问题,因为我现在知道“login”参数然后能够 ActiveMerchant: :Billing::Base::gateway.(:trust_commerce).("login" => "value")。有趣的是,当我这样做时,它给了我一个无方法错误!
    • 从技术上讲,您关于“阅读文档”的答案是迄今为止唯一有效的答案,因为有关该方法的官方文档字面上是这样说的 rubydoc.info/gems/activemerchant/ActiveMerchant/Billing/… 但这引发了另一个问题。官方 Ruby 文档对 parameters 方法有误吗?在我的情况下,它给了我一个无方法错误,而它只是应该给我我想要的方法的参数。有对此的解释吗?
    猜你喜欢
    • 1970-01-01
    • 2011-03-19
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 2016-06-09
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多