【问题标题】:Porting Java to Ruby - How to handle method signature overloading将 Java 移植到 Ruby - 如何处理方法签名重载
【发布时间】:2015-01-02 17:50:21
【问题描述】:

我在将一些 java 代码移植到 ruby​​ 中获得了一些乐趣,我正在寻求有关如何最好地实现以下方法签名重载的指导?

使用 Ruby 的可选参数,我可以适应所有的重载,但这会导致不太理想的“条件”编码来确定我正在处理的参数。有什么更“像 Ruby 一样”的方式来处理这个问题?

  # public void set (ISOComponent c)
  # public void set(int fldno, String value)
  # public void set (String fpath, String value)
  # public void set (String fpath, ISOComponent c)
  # public void set (String fpath, byte[] value)
  # public void set (int fldno, byte[] value)
  def set(iso_component: nil, field_number: -1, string_value: '', file_path: '', byte_array: nil)

【问题讨论】:

  • 不幸的是,ruby 中没有方法签名重载。我能想到的唯一合理的替代方法是为每个签名设置单独的方法:set_iso_componentset_field_number_and_string_value 等。

标签: java ruby overloading optional-parameters


【解决方案1】:

对于 Ruby,我认为您最好的选择是依赖不同的 OOP 设计原则,例如鸭子类型。与其尝试创建一个 set 方法来执行 6 种不同的事情,具体取决于您传递给它的参数,如果您创建共享可以作为参数传递的一致接口的对象,您的代码最终可能会更清晰和更易于维护到您的set 方法。这是一个例子:

class MyObject
  def set(obj)
    # depend on the interface: duck typing
    obj.set_the_things
  end
end

class ISOComponent
  def set_the_things
    # do ISOComponent specific stuff here
  end
end

class OtherInput
  attr_accessor :field_number, :value

  def set_the_things
    # do OtherInput specific stuff here
    # using @field_number and @value
  end
end

my_obj = MyObject.new
iso_component = ISOComponent.new
other_input = OtherInput.new

my_obj.set(iso_component)
my_obj.set(other_input)

由于MyObject#set 仅依赖于可以传递给它的对象中的set_the_things 方法,因此您可以将任意数量的不同对象传递给此方法,只要它们实现自己的set_the_things 方法即可执行特定于其目的的行动。因此,如果您需要一个处理文件路径和 ISO 组件的输入,您将构建一个具有 set_the_things 方法的对象,该方法对文件路径和 ISO 组件执行所需的操作,而不是尝试制作您的 set 方法成为所有人的一切(这对于测试和需要了解 set 方法的客户来说可能更令人困惑)。

文章“Duck Typing”对此进行了描述。

【讨论】:

    【解决方案2】:

    在 Ruby 中重载方法是不可能的,您需要重构 API,或者您可以进行一些花哨的元编程并评估类型并调用不同的方法定义(您使用类似 DSL 的方法定义)但这绝对是这不是我认为的标准方式。

    通常,如果您有一个困难的方法,您可能希望将参数作为散列传递,并为字段定义默认值。如果您有多个类需要评估为一种目标类型,您可以定义一个方法,将所有这些类型转换为您想要的目标类型。

    好吧,我觉得我更擅长用代码表达自己:

    def set(options = {})
      options[:str] = (options[:str] || "").to_s
      options[:num] = (options[:num] || 0).to_i
    end
    

    在这里,您可以使用几乎在任何东西上定义的 to_ito_s 方法,但是您可以定义自己的“转换器”方法来转换为您想要的类,然后您就不必费心了在你的方法中关于变量的类型。

    还有一件很酷的事情是,在 ruby​​ 中,括号是可选的,您可以在不使用花括号的情况下调用早期的方法。

     # These two are equivalent to eachother
     set({str: "Hello World", num: 123})
     set(str: "Hello World", num: 123)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多