概要
Rubyのrefineメソッドについて。usingメソッドとセットで使用する。
メソッドの再定義を行える。再定義した内容をグローバルに影響させたくない場合とかで使用する。
基本
こんな感じ。using以降から有効になる。usingはファイルの末尾か、クラス定義内ならクラス定義の末尾まで有効
class C
def c_method
p 'Cのメソッドだよ'
end
end
module M
refine C do
def c_method
p 'refineで定義し直したよ'
end
end
end
c = C.new
c.c_method
=> 'Cのメソッドだよ'
using M
c.c_method
=> 'refineで定義し直したよ'
self
refine内のブロックは無名モジュール。クラスのコンテキストではないので定数なんかは参照できない
class C
CCONST = 'Cの定数だよ'
end
module M
refine C do
p self
# => #<refinement:C@M>
CCONST # Cのスコープじゃないのでエラー
# => NameError
end
end
メソッド探索
prependより優先される。以下の順序
refine < prependしたモジュール < クラス < includeしたモジュール < 親クラス
module P
def c_method
p 'prependのメソッドだよ'
end
end
class C
prepend P
def c_method
p 'Cのメソッドだよ'
end
end
module M
refine C do
def c_method
p 'refineで定義し直したよ'
end
end
end
c = C.new
c.c_method
=> 'prependのメソッドだよ'
using M
c.c_method
=> 'refineで定義し直したよ'
クラスメソッド
クラスメソッドのときはsingleton_classを使う。selfは使わない
class C
def self.c_method
p 'Cのクラスメソッドだよ'
end
end
module M
refine C.singleton_class do
def c_method
p 'refineで定義し直したクラスメソッドだよ'
end
end
end
using M
C.c_method
=> 'refineで定義し直したクラスメソッドだよ'
メソッド再定義
usingの後にメソッド再定義してもusingが有効
class C
def c_method
p 'Cのメソッドだよ'
end
end
module M
refine C do
def c_method
p 'refineで定義し直したメソッドだよ'
end
end
end
using M
class C
def c_method
p '再定義したCのメソッドだよ'
end
end
c = C.new
c.c_method
=> 'refineで定義し直したメソッドだよ'
複数のusing
複数usingの場合は最後のusingのみ有効
class C
def c_method
p 'Cのメソッドだよ'
end
end
module M1
refine C do
def c_method
p 'M1 refineで定義し直したメソッドだよ'
end
end
end
module M2
refine C do
def c_method
p 'M2 refineで定義し直したメソッドだよ'
end
end
end
using M1
using M2
c = C.new
c.c_method
=> 'M2 refineで定義し直したメソッドだよ'
メソッド定義内でusing
メソッド定義内でusingは呼び出せない。エラーになる
class C
def c_method
p 'Cのメソッドだよ'
end
end
module M
refine C do
def c_method
p 'refineで定義し直したメソッドだよ'
end
end
end
def call_using
using M
end
call_using
=> RuntimeError
super
refineで定義したメソッド内でsuperを呼び出すと定義元のメソッドが呼ばれる
class C
def c_method
p 'Cのメソッドだよ'
end
end
module M
refine C do
def c_method
p 'refineで定義し直したメソッドだよ'
super
end
end
end
using M
c = C.new
c.c_method
=> 'refineで定義し直したメソッドだよ'
'Cのメソッドだよ'
0 件のコメント:
コメントを投稿