2019-08-03
StructとOpenStruct
似た名前だが意外と挙動が異なるな、と思ったのでメモ。
Struct
# クラスをつくる
> Man = Struct.new(:age, :sex) # => Man
> Man.class # => Class
# クラスからインスタンスをつくる
> taro = Man.new(28, :male) # => #<struct Man age=28, sex=:male>
> taro.class # => Man
# 定義した属性を利用できる
> taro.age += 1
> taro.age # => 29
# 定義していない属性は利用できない
> taro.job = :engineer # NoMethodError: undefined method `job=' for #<struct Man age=28, sex=:male>
OpenStruct
# コアライブラリではなく標準ライブラリ
> require 'ostruct'
# newするとシンプルにOpenClassインスタンスが返ってくる
> taro = OpenStruct.new({age: 28, sex: :male}) # => #<OpenStruct age=28, sex=:male>
> taro.class # => OpenStruct
# 定義した属性を利用できる
> taro.age += 1
> taro.age # => 28
# 定義していなかった属性も利用できる
> taro.job = :engineer # => :engineer
> taro.job # => :engineer
違い
「最初に定義してない属性を利用できる/できない」というのは Struct/OpenStruct という名前から想像できたので問題なし。
意外だったのは以下の違い。
- Struct.new では Class インスタンス(ex. taro)をつくる
- 最も具体的なオブジェクトを生成するまでに 2 段階を要する。
- 普通にクラスを定義している感覚。
- OpenStruct.new ではいきなり OpenStruct インスタンスがつくられる
- 最も具体的なオブジェクトを生成するまでに 1 段階のみ要する。
- クラス定義というよりは、ハッシュを生成している感覚。
- (Hash との最大の違いは、メソッドをもたせられることかな?たぶん)