Ruby 3.2 リファレンスマニュアル > ライブラリ一覧 > 組み込みライブラリ > Dataクラス > define
define(*args) -> Class
[permalink][rdoc]define(*args) {|subclass| block } -> Class
Data クラスに新しいサブクラスを作って、それを返します。
サブクラスでは値オブジェクトのメンバに対するアクセスメソッドが定義されています。
Dog = Data.define(:name, :age)
fred = Dog.new("Fred", 5)
p fred.name # => "Fred"
p fred.age # => 5
メンバの値を書き換えることはできません。
Dog = Data.define(:name, :age)
fred = Dog.new("Fred", 5)
fred.age = 6 # => NoMethodError
メンバを持たないサブクラスも定義可能です。以下のように、パターンマッチに利用できます。
class HTTPFetcher
Response = Data.define(:body)
NotFound = Data.define
def get(url)
# ダミーの実装
if url == "http://example.com/"
Response.new(body: "Current time is #{Time.now}")
else
NotFound.new
end
end
end
def fetch(url)
fetcher = HTTPFetcher.new
case fetcher.get(url)
in HTTPFetcher::Response(body)
body
in HTTPFetcher::NotFound
:NotFound
end
end
p fetch("http://example.com/") # => "Current time is 2023-01-10 10:00:53 +0900"
p fetch("http://example.com/404") # => :NotFound
Data.define にブロックを指定した場合は定義した Data をコンテキストにブロックを評価します。また、定義した Data はブロックパラメータにも渡されます。
Customer = Data.define(:name, :address) do
def greeting
"Hello #{name}!"
end
end
p Customer.new("Dave", "123 Main").greeting # => "Hello Dave!"
なお、Dataのサブクラスのインスタンスを生成する際にオプション引数を使用したいときは、 initialize メソッドをオーバーライドすることで実現できます。
Point = Data.define(:x, :y) do
def initialize(x:, y: 0)
super
end
end
p Point.new(x: 1) # => #<data Point x=1, y=0>
p Point.new(x: 1, y: 2) # => #<data Point x=1, y=2>