読者です 読者をやめる 読者になる 読者になる

Tbpgr Blog

Ruby プログラマ tbpgr(てぃーびー) のブログ

Ruby | Collecting Inputs | 明示的変換と暗黙の変換(explicit conversion and implicit conversion)

Confident Ruby Ruby

概要

明示的変換と暗黙の変換(explicit conversion and implicit conversion)

前提

Confident Rubyではメソッド内の処理を次のように分類しています。
・Collecting Inputs(引数チェック、変換など)
・Performing Work(主処理)
・Delivering Output(戻り値に関わる処理)
・Handling Failure(例外処理)

当記事は上記のうち、Collecting Inputsに関する話です。

詳細

明示的変換と暗黙の変換(explicit conversion and implicit conversion)について。
Stringクラスでいうとto_sが明示的変換,to_strが暗黙的変換にあたります。

to_sは文字列化が主目的。
to_strはStringのダックタイピングが主目的。

Stringのように振る舞わせたいクラスにto_strを実装することで、
暗黙の変換を期待します。

逆に、Stringのように振る舞うクラスを扱うメソッド側では引数に対して
respond_to?でto_strの有無を確認し、
・to_strがなければエラー
・to_strがあれば呼び出して以降の処理を行う
ことで引数がStringクラスであるかチェックする場合と比べて
寛容なインターフェースを提供することができるため、
利用側にとって使いやすくなります。

サンプルコード

to_strの利用例。
仮にPersonクラスを文字列のように振る舞わせたいとします。

class Person
  attr_reader :name, :age

  def initialize(name, age)
    @name, @age = name, age
  end

  def to_str
    @name
  end
end

class NotStringPerson
  attr_reader :name, :age

  def initialize(name, age)
    @name, @age = name, age
  end

  def to_s
    @name
  end
end

tanaka = Person.new("tanaka", 34)
puts tanaka.to_s
puts tanaka.to_str

# + 演算子利用時に暗黙的にto_strを利用した変換が行われる
puts "name = " + tanaka
puts "tanaka".include?(tanaka)

class StringUser
  def self.use_string(text)
    fail 'error!' unless text.respond_to? :to_str
    text = text.to_str
    puts text.upcase
  end
end

StringUser.use_string("hoge")
StringUser.use_string(tanaka)
tanaka2 = NotStringPerson.new("tanaka", 34)
# raise error
# StringUser.use_string(tanaka2)

出力

#<Person:0x25ccad0>
tanaka
name = tanaka
true
HOGE
TANAKA