スキップしてメイン コンテンツに移動

Structで簡易値オブジェクト

Structで簡易値オブジェクト

Ruby実践でのStructとOpenStruct

Rubyではデータ保持に便利な構造体が用意されています。Structはクラスを簡易定義でき、OpenStructは属性を動的に追加できる軽量クラスです。両者ともドットアクセスで値を取得・設定できるため、コードが読みやすくなります。

require 'ostruct'

# Structで簡易定義
User = Struct.new(:name, :email)

u = User.new('Alice', 'alice@example.com')
puts u.name   # => Alice

# OpenStructで動的に属性を追加
profile = OpenStruct.new(name: 'Bob')
profile.age = 30
puts profile.age   # => 30

Structはコンパイル時に固定された属性を持つため、パフォーマンスが若干優れます。一方、OpenStructは属性が自由に増減できるため、柔軟性が必要な場面で活躍します。

軽量クラスとしての構造体

構造体は値オブジェクトとして扱われることが多く、イミュータブルなデータを保持するのに適しています。RubyのStructは内部でStruct::newを呼び出すだけでクラスを生成できるため、軽量クラスとして即座に利用できます。

Point = Struct.new(:x, :y) do
  def distance_from_origin
    Math.sqrt(x**2 + y**2)
  end
end

p = Point.new(3, 4)
puts p.distance_from_origin   # => 5.0

このように、構造体はドットアクセスで属性にアクセスでき、メソッドを追加して機能を拡張することも可能です。値オブジェクトとして扱う場合は、freezeでイミュータブルにすることも推奨されます。

値オブジェクトとしての使い方

値オブジェクトは等価性を属性で判断し、変更不可であることが前提です。RubyのStructはデフォルトで==を属性比較に基づいて実装しているため、値オブジェクトとして即座に利用できます。

Address = Struct.new(:street, :city, :zip)

a1 = Address.new('1-1', 'Tokyo', '100-0001')
a2 = Address.new('1-1', 'Tokyo', '100-0001')

puts a1 == a2   # => true

さらに、freezeを呼び出すことでオブジェクトをイミュータブルにし、予期せぬ変更を防げます。

a1.freeze
# a1.street = '2-2'  # => RuntimeError: can't modify frozen Address

このように、StructやOpenStructを活用することで、Ruby実践においてデータ保持と軽量クラスの設計を簡易定義で実現し、ドットアクセスで直感的に扱える値オブジェクトを作成できます。

この記事はAIによって作成されました。

コメント