k0kubunс

経緯や意図については私は認識していませんが、
渡されたオブジェクトの型がStringの場合はそれをそのまま使うという挙動のため、
Refinementsに限った話ではなく、グローバルにString#to_sを再定義しても呼ばれないと思います。

個人的には String#to_s を上書きしたいことがないので
後方互換性的にもそのままの挙動で構わないのですが、
私もこの挙動を見たときは一貫性がないように感じたので
これが意図的なのかどうかは経緯に詳しい方にお聞きしたいです。

2017年8月9日 23:43 Tsukuru Tanimichi <ttanimichi / ttanimichi.com>:
> はじめまして。谷道と申します。
>
> 既出だったらすみません。bugs.ruby-lang.org でも検索したんですが
> それっぽいチケットが見当たらなかったので確認させてください。
>
> Refinements で定義した to_s を String interpolation が呼んでくれないのですが、これって仕様なんですかね?
> String literal の評価が using B しているスコープの外で行われる、ということでしょうか。
>
> ```
> $ ruby -v
> ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
> ```
>
> ```ruby
> class A
> end
>
> module B
>   refine A do
>     def to_s
>       'b'
>     end
>   end
> end
>
> class C
>   using B
>
>   def initialize
>     @a = A.new
>   end
>
>   def c1
>     @a.to_s
>   end
>
>   def c2
>     "#{@a}"
>   end
>
>   def c3
>     puts "#{@a}"
>   end
> end
>
> puts C.new.c1 #=> b
> puts C.new.c2 #=> #<A:0x007fb05ba3e928>
> C.new.c3 #=> #<A:0x007fb05ba3e7e8>
> ```
>
> c1, c2, c3 ともに "b" となることを想像していました。
>
> --
> 谷道 創(Tsukuru Tanimichi)
> https://ttanimichi.com/