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!
参照
-
http://docs.ruby-lang.org/ja/2.1.0/method/Object/i/to_s.html
-
http://docs.ruby-lang.org/ja/2.1.0/method/Object/i/to_str.html
-
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