⛳
Ruby の Data と Struct の違い
Ruby 3.2 で新たに Data
クラスが追加されました。
これは既存の Struct
クラスと似た機能になるんですが少し異なる部分もあるのでまとめました。
定義メソッドが異なる
Struct
では .new
メソッドで新しくクラスオブジェクトを定義するんですが Data
は .define
で定義します。
# .new で User クラスを定義する
User = Struct.new(:name, :age)
# .define で Blog クラスを定義する
Blog = Data.define(:ttile, :owner)
Data.define
ではいくつかのメソッドがオミットされている
Struct.new
では Enumerable
を mix していたり Hash
ぽいメソッドがいくつか定義されています。
User = Struct.new(:id, :name, :age)
pp User.ancestors
# => [User, Struct, Enumerable, Object, Kernel, BasicObject]
homu = User.new(1, "homu", 14)
# 値だけ抽出する
pp homu.values
# => [1, "homu", 14]
# String の値だけ抽出する
pp homu.select { String === _1 }
しかし Data
では Enumerable
は mixin されておらず #values
のようなメソッドも定義されていません。
User = Data.define(:id, :name, :age)
pp User.ancestors
# => [User, Data, Object, Kernel, BasicObject]
homu = User.new(1, "homu", 14)
# イテレーションしたい場合は #to_h などを経由してアクセスする
pp homu.to_h.values
pp homu.to_h.values.select { String === _1 }
Data.define
ではクラス名を指定できない
Struct.new
の第一引数に文字列を渡すことでその名前で Struct
の内部クラスとして定義されます。
user = Struct.new("User", :name, :age)
pp user.name
# => "Struct::User"
# クラスを直接参照する事もできる
pp Struct::User
ただし、Data
にはこの機能はありません。
# この場合は単純に "User" という名前のメンバーが定義されるだけ
user = Data.define("User", :name, :age)
pp user.members
# => [:User, :name, :age]
一旦こんなところですかね?細かいところで他にもあるかも。
Discussion