14

mixin メソッド内でインスタンス変数にアクセスするにはどうすればよいですか? 2つの方法が考えられますが、どちらも問題があるようです。

  1. 任意のクラス メソッドと同じように、mixin メソッドがインスタンス変数に直接アクセスするようにします (例: self.text)。これに関する問題は、mixin メソッドを使用できる場所に制限を課し、ミキシングを行うクラスに特定の方法で名前を付けた特定のインスタンス メソッドを持たせることです。

  2. インスタンス変数をパラメーターとして mixin メソッドに渡すと、次のようなコードになります。

self.do_something(self.text)

また

@thing.do_something(@thing.text)

これは私には厄介に見え、オブジェクト指向の原則に準拠していません。

それを行う他の方法はありますか?、心配するのは正しいですか?

4

3 に答える 3

28

一般に、ミックスインがメンバー変数にアクセスすることは避けてください。これは、将来のリファクタリングを不必要に困難にする可能性がある結合の非常に緊密な形式です。

有用な戦略の 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

ミックスインで一般的なデータ名を使用すると、含まれているクラスが同じ名前を使用している場合に競合が発生する可能性があります。その場合、あまり一般的でない名前のデータを mixin で検索するようにします。

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"

このように、アクセサーは、ミックスインのデータと含まれるクラスのデータの間で、一種の「インピーダンス マッチャー」または「トランスレーター」として機能します。

于 2010-02-19T15:46:50.650 に答える
2

インスタンス変数名はルビで @ で始まります。@variable. 含めるモジュールからこの名前でそれらにアクセスできます

module M
  def t
    @t
  end
end

class A
  include M
  def initialize(t)
     @t= t
  end
end

A.new(23).t # => 23

@tこの方法でアクセスする前に、クラスで定義されていないときにアクセスしたくない場合

module M
  def t
    instance_variable_defined?("@t") ? @t : nil
  end
end
于 2010-02-19T14:51:02.127 に答える
1

このモジュールでこのインスタンスメソッドを自分で指定できますが、既存のメソッドを上書きしないように注意する必要があります

例(混合しているモジュール内):

def text
    @text ||= ""
end
于 2010-02-19T10:10:13.490 に答える