【Ruby 3.4 Advent Calender】Refinement#refined_class が削除された【22日目】
Ruby 3.4 Advent Calender 22日目の記事です。
これはなに
今年 2024年12月25日にリリースされる予定の Ruby 3.4 の新機能や変更点などを1つずつ紹介していく Advent Calender になります。
基本的には NEWS に載っている機能を紹介すると思うんですがここにない機能についても書くかもしれません。
また、記事を書いてる時点ではまだ Ruby 3.4 はリリースされる前なので Ruby 3.4 がリリースされた時点で機能が変わっている 可能性があるかもしれないので注意してください。
記事のまとめは ここを参照 してください。
Refinement#refined_class
が削除された
Ruby 3.4 以前では refine
されているクラスを取得する Refinement#refined_class
メソッドがありました。
例えば refine
のブロック内から refine
されているオブジェクトを #refined_class
メソッドで取得することができました。
module Ext
refine String do
# refine されているオブジェクトを取得できる
pp refined_class # => String
end
refine String.singleton_class do
# singleton_class みたいなのも取得できる
pp refined_class # => #<Class:String>
end
end
この #refined_class
メソッドが Ruby 3.4 では削除されました。
変わりに Ruby 3.3 から追加された Refinement#target
メソッドが利用できます。
module Ext
refine String do
# #refined_class と同じ値を返す
pp target # => String
end
end
Refinement#refined_class
を使用している場合は使用するメソッドを変更する必要があるので注意してください。
背景
#refined_class
という名前のメソッドなんですが実際には『 class
ではなくて module
オブジェクトを返す』ケースも存在しています。
例えば以下のように refine
に module
を渡した場合ですね。
module Ext
# module オブジェクトに対して refine した場合は当然 module のオブジェクトが返ってくる
refine Enumerable do
pp refined_class
end
end
これが名前と実態があっていないということで以下のチケットで Refinement#refined_module
を追加する提案がされました。
最終的にこのチケットでは Ruby 3.3 では以下の対応がされることが決定しました。
- Ruby 3.3 で
#refined_class
と同等の#target
という名前のメソッドを追加する - Ruby 3.3 では
#refined_class
を使用すると警告を出すようにする-
-W:deprecated
が有効な場合に警告がでる
-
- Ruby 3.4 では
#refined_class
を削除する
なので Ruby 3.3 では以下のような挙動になります
Warning[:deprecated] = true
module Ext
refine Enumerable do
# no warning
pp target # => Enumerable
# warning: Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead
pp refined_class # => Enumerable
end
end
Discussion