LoginSignup
19
18

More than 5 years have passed since last update.

Ruby | 文字列への明示的変換と暗黙的変換。Object#to_s , Object#to_str の使い分け

Posted at

Ruby | 文字列への明示的変換と暗黙的変換。Object#to_s , Object#to_str の使い分け

概要

文字列への明示的変換と暗黙的変換。Object#to_s , Object#to_str の使い分けについて。

Object#to_s と Object#to_str に関する Matz さんの発言

Matz さんの発言

to_sは(どのオブジェクトにもデフォルトで定義されている)文字列
化のフォーマットを変えるために再定義します。

to_strはそのクラス/オブジェクトが文字列として振る舞うことが
できるようにするために定義します。

Object#to_s

るりまのドキュメント

明示的な変換。

Kernel#print や文字列の変数展開でも使われている to_s。
オブジェクトの文字列表現を返却する。

オブジェクトの文字列化が目的。

Object#to_str

るりまのドキュメント

暗黙的な変換。

文字列の + 演算子利用時に呼び出されている to_str。

Matz さんの発言

Stringと類似のメソッド集合を持たないオブジェクトはto_strを定義するべ
きではないように思います(実害がない限り)。

ダックタイピングが目的。

つまり、String のように振る舞う

to_str の実装例

Rails の ActiveView の Template で to_str を実装していました

ActiveView::Template::Text / HTML / Resolver

https://github.com/rails/rails/blob/master/actionview/lib/action_view/template/text.rb
https://github.com/rails/rails/blob/master/actionview/lib/action_view/template/html.rb
https://github.com/rails/rails/blob/master/actionview/lib/action_view/template/resolver.rb

to_s , to_str の動作確認用サンプルコード

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)
suzuki = NotStringPerson.new("suzuki", 44)
puts "■ to_s, to_str を直接呼び出し"
puts "tanaka.to_s = " + tanaka.to_s
puts "tanaka.to_str = " + tanaka.to_str
puts "suzuki.to_s = " + suzuki.to_s
begin
  puts "suzuki.to_str = " + suzuki.to_str
rescue => e
  puts e.message
end

# + 演算子利用時に暗黙的に to_str を利用した変換が行われる
puts "■ + 演算子利用時の to_str  呼び出し確認"
puts "tanaka name = " + tanaka
begin
  puts "suzuki name = " + suzuki
rescue => e
  puts e.message
end

# 変数展開時にも暗黙的に to_s を利用した変換が行われる
puts "■ 変数展開"
puts "tanaka name = #{tanaka}"
puts "suzuki name = #{suzuki}"

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

puts "■ StringUser クラスから呼び出し"
StringUser.use_string("hoge")
StringUser.use_string(tanaka)
begin
  StringUser.use_string(suzuki)
rescue => e
  puts e.message
end
  • 出力
■ to_s, to_str を直接呼び出し
tanaka.to_s = #<Person:0x2bcd370>
tanaka.to_str = tanaka
suzuki.to_s = suzuki
undefined method `to_str' for #<NotStringPerson:0x2bcd328 @name="suzuki", @age=44>
■ + 演算子利用時の to_str  呼び出し確認
tanaka name = tanaka
no implicit conversion of NotStringPerson into String
■ 変数展開
tanaka name = #<Person:0x2bcd370>
suzuki name = suzuki
■ StringUser クラスから呼び出し
HOGE
TANAKA
error!

参照

19
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
18