【Ruby】移譲(Delegation)とは?

Ruby
記事内に広告が含まれています。

はじめに

あるオブジェクトが受け取ったメソッド呼び出しを、別のオブジェクトに丸投げする仕組みを移譲(Delegation)と呼びます。

移譲の基礎

UserクラスがProfileクラスを持ち、Profilenameを取得するケースを考えます。

class Profile
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

class User
  def initialize(profile)
    @profile = profile
  end

  def name
    @profile.name  # 呼び出しをそのままprofileに移譲
  end
end

profile = Profile.new("Tanaka")
user = User.new(profile)
puts user.name  # => "Tanaka"

これが移譲の基本です。
このようにuser.name と書くと、裏側では profile.name が呼ばれるようにするのが移譲です。

手書き移譲の欠点

例えばProfileからnameだけでなくageemailも取りたい場合…

class User
  def initialize(profile)
    @profile = profile
  end

  def name
    @profile.name
  end

  def age
    @profile.age
  end

  def email
    @profile.email
  end
end

同じようなコードを何度も書くことになります。
この繰り返しは保守性を下げ、修正漏れの原因にもなります。

※なお、この例ではProfileクラスにageおよびemailの定義を追加する必要があります。

Forwardableによる効率化

Rubyには標準でForwardableモジュールがあり、このような移譲を簡単に書くことができます。

require 'forwardable'

class User
  extend Forwardable

  def_delegators :@profile, :name, :age, :email

  def initialize(profile)
    @profile = profile
  end
end

これだけで、

user.name
user.age
user.email

を使えるようになります。

Forwardableのポイント

extend Forwardableでクラスメソッドとしてdef_delegatorsが使えるようになる。
def_delegatorsの第一引数に移譲先オブジェクト(ここでは@profile)を指定し、第二引数以降に移譲したいメソッド名を並べる。

まとめ

  • 移譲とは、メソッド呼び出しを別のオブジェクトにそのまま渡す仕組み
  • 純粋なRubyでも簡単に実装できるが、メソッド数が増えると面倒
  • Ruby標準のForwardableを使えば、移譲をまとめて定義できる

最後までお読みいただきありがとうございました。

皆さんからのコメントやSNSでのシェア、嬉しい投稿をいただくと本当に励みになります。

もしこの記事が気に入ったら感想をコメントやSNSでシェアしていただけると嬉しいです。

皆さんの声を聞かせてくださいね!

Ruby
tetsuをフォローする
簿記はじめるってよ

コメント

タイトルとURLをコピーしました