【问题标题】:How to express this data type in Ruby?如何在 Ruby 中表达这种数据类型?
【发布时间】:2021-03-17 05:31:57
【问题描述】:

我有这个描述类型的 preudo 代码

    type MyType1 = {
        type: :type1,
        field1: number,
        field2: any
    } | {
        type: :type2,
        field3: string
    } | {
        type: :type4,
        field4: SomeOtherType
    } | {
        type: :type5,
        field5: string,
        field6: integer,
        field7: float
    } | {
        type: :type6
    }

我在 Ruby 中是这样表达的:

    class MyType1
        attr_reader :type, :field1, :field2, :field3, :field4, :field5, :field6, :field7

        def init_with_type_1(field1:, field2:)
          @type = :type1
          @field1 = field1
          @field2 = field2
        end

        def init_with_type_2(field3:)
          @type = :type2
          @field3 = field3
        end

        # and so on...

    end

有没有更好、更惯用、更简单的方法?

我不考虑使用第三方 gems 和库。

【问题讨论】:

  • 更好更简单的方法是只使用函数和映射。但这并不一定更惯用,因为在 Ruby 中编写函数式代码可能很笨重。
  • 在 Ruby 中,我可能会定义一个超类 Type 和子类 Type1Type2 等。
  • 策略模式?

标签: ruby types ruby-3


【解决方案1】:

我会这样做:

Type1 = Struct.new(:field1, :field2)
Type2 = Struct.new(:field3)

class MyType1
  def initialize(some_type_item)
    @data = some_type_item
  end
  def self.init_with_type_1(f1, f2)
    self.new(Type1.new(f1,f2))
  end
  def type
    @data.class # Or @data.class.name, if you prefer
  end
  def field1
    # Raises exception, if we don't have Type1 
    @data.field1
  end
end

我对此进行了明确编码,但是使用 Ruby 标准库中的 Forwardable 模块可以使一些工作(例如 field1 的定义等)变得更简单(更少的输入)。此外,init_with_type 方法可以使用循环生成,如果您想在此处存储许多不同的类型,这可以简化事情。

虽然我问自己,我为这个接近你最初的解决方案建模,但为什么你为此引入一个类MyType1;在定义了 Type1、Type2 等之后,我会简单地做一个

myTypeVar = Type2.new(4711)
puts "myTypeVar is a #{myTypeVar.class}"
puts myTypeVar.field3 # OK
puts myTypeVar.field1 # Exception!

【讨论】:

  • 即使那代表MyType1,它并没有简化事情,而是把事情复杂化了。
  • @Khinkala2 :实际上,这就是我在下面写下我将如何解决这个问题的原因。 IMO,在这里发明 MyType1 是不必要的。如果所有类型都共享某些特性,也许你最好使用 Module 作为 mixin。除非我们看到您打算如何使用该类型,否则很难推荐。顺便说一句:如果您手动输入所有方法,我的方法看起来很复杂。我这样做只是为了清楚起见,但如果您有许多嵌套类型,您将使用循环生成它们,这样最终会减少代码。例如,您可以自动生成 fieldninit_with_typen_ 方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-06
  • 2022-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多