mixin メソッド内でインスタンス変数にアクセスするにはどうすればよいですか?
概要
mixin メソッド内でインスタンス変数にアクセスするにはどうすればよいですか? 2つの方法が考えられますが、どちらも問題があるようです。
例
self.do_something(self.text)
または
@thing.do_something(@thing.text)
これは私には不快に思えますし、オブジェクト指向の原則にも準拠していません。
他に方法はありますか?心配しても大丈夫ですか?
解決策
一般に、ミックスインがメンバー変数にアクセスできるようにすることは避けてください。これは非常に密接な結合形式であり、将来のリファクタリングを不必要に困難にする可能性があります。
有用な戦略の 1 つは、Mixin が常にアクセサーを介して変数にアクセスすることです。したがって、代わりに:
#!/usr/bin/ruby1.8
module Mixin
def do_something
p @text
end
end
class Foo
include Mixin
def initialize
@text = 'foo'
end
end
Foo.new.do_something # => "foo"
ミックスインは、インクルード クラスによって定義される「テキスト」アクセサーにアクセスします。
module Mixin
def do_something
p text
end
end
class Foo
attr_accessor :text
include Mixin
def initialize
@text = 'foo'
end
end
Foo.new.do_something # => "foo"
このクラスに Mixin を含める必要がある場合はどうすればよいでしょうか?
class Foo
def initialize
@text = "Text that has nothing to do with the mixin"
end
end
ミックスインで汎用の一般的なデータ名を使用すると、包含クラスが同じ名前を使用している場合に競合が発生する可能性があります。その場合、ミックスインにあまり一般的ではない名前のデータを検索させます。
module Mixin
def do_something
p mixin_text
end
end
そして、インクルードクラスに適切なアクセサーを定義させます。
class Foo
include Mixin
def initialize
@text = 'text that has nothing to do with the mixin'
@something = 'text for the mixin'
end
def mixin_text
@something
end
end
Foo.new.do_something # => "text for the mixin"
このように、アクセサーは、ミックスインのデータとそれを含むクラスのデータの間で、一種の「インピーダンス マッチャー」または「トランスレーター」として機能します。