class Data

Class Data 提供了一种便捷的方式来定义简单的、值相似对象的类。

最简单的用法示例

Measure = Data.define(:amount, :unit)

# Positional arguments constructor is provided
distance = Measure.new(100, 'km')
#=> #<data Measure amount=100, unit="km">

# Keyword arguments constructor is provided
weight = Measure.new(amount: 50, unit: 'kg')
#=> #<data Measure amount=50, unit="kg">

# Alternative form to construct an object:
speed = Measure[10, 'mPh']
#=> #<data Measure amount=10, unit="mPh">

# Works with keyword arguments, too:
area = Measure[amount: 1.5, unit: 'm^2']
#=> #<data Measure amount=1.5, unit="m^2">

# Argument accessors are provided:
distance.amount #=> 100
distance.unit #=> "km"

构造的对象还具有合理的定义,例如 == 运算符、to_h 哈希转换,以及 deconstruct / deconstruct_keys,可用于模式匹配。

::define 方法接受一个可选的块,并在新定义的类的上下文中对其进行求值。这允许定义额外的​​方法。

Measure = Data.define(:amount, :unit) do
  def <=>(other)
    return unless other.is_a?(self.class) && other.unit == unit
    amount <=> other.amount
  end

  include Comparable
end

Measure[3, 'm'] < Measure[5, 'm'] #=> true
Measure[3, 'm'] < Measure[5, 'kg']
# comparison of Measure with Measure failed (ArgumentError)

Data 不提供成员写入器或枚举器:它旨在存储不可变原子值。但请注意,如果任何数据成员是可变类的实例,Data 不会强制执行额外的不可变性。

Event = Data.define(:time, :weekdays)
event = Event.new('18:00', %w[Tue Wed Fri])
#=> #<data Event time="18:00", weekdays=["Tue", "Wed", "Fri"]>

# There is no #time= or #weekdays= accessors, but changes are
# still possible:
event.weekdays << 'Sat'
event
#=> #<data Event time="18:00", weekdays=["Tue", "Wed", "Fri", "Sat"]>

另请参阅 Struct,它是一个类似的概念,但具有更像容器的 API,允许更改对象内容并对其进行枚举。