圧倒亭グランパのブログ

30年後の自分にもわかるように書くブログ

Crystalのmacro紹介 "delegate"

この記事は、 Crystal Advent Calendar 2017 の7日目の記事です。

crystalには便利なmacroがあります。macroを使えば、記述量も削減でき表現力も向上します。しかし、ただcrystalを書いているだけでは、なかなかそれらのmacroに出会うことができません。

ということで、アドベント・カレンダーの日数稼ぎも兼ねて、macroの紹介をしたいと思います。

そもそも「macroってなんだ」という場合は、下記の本家docsを参照してください。

Macros · GitBook

 

今回は、 delegate を紹介します。

delegate

crystal-lang.org/api - Object - delegate

fieldのオブジェクトに処理を委譲させます。シグネチャは以下です。

macro delegate(*methods, to object)

通常、メソッドの委譲は、以下のように行います。

class User
  def initialize(@name : String, @age : Int32)
  end

  def greeting
    "Hi, my name is #{@name}."
  end
end

class PremiumUser
  def initialize(name : String, age : Int32)
    @user = User.new(name, age)
  end

  # オブジェクトに処理を委譲
  def greeting
    @user.greeting
  end
end

premium_user = PremiumUser.new "Taro", 30
p premium_user.greeting # => "Hi, my name is Taro."

これをmacroのdelegateを使うとこうなります。

class User
  def initialize(@name : String, @age : Int32)
  end

  def greeting
    "Hi, my name is #{@name}."
  end
end

class PremiumUser
  def initialize(name : String, age : Int32)
    @user = User.new(name, age)
  end

  # オブジェクトに処理を委譲するmacro
  delegate greeting, to: @user
end

premium_user = PremiumUser.new "Taro", 30
p premium_user.greeting # => "Hi, my name is Taro."

delegete {メソッド名}, to: {委譲先オブジェクト名} として、メソッドを委譲先オブジェクトに任せます。delegete A to Bのような英語風味なところも良いですね。

ぜひ使ってみてください。