class Data

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,允许更改对象的内容并对其进行枚举。