14

如何在 mixin 方法中访问实例变量?我可以想到两种方法,但似乎都有问题。

  1. 让 mixin 方法像任何类方法一样直接访问实例变量,例如 self.text。这样做的问题是它限制了 mixin 方法的使用位置,并强制进行混合的类具有以特定方式命名的特定实例方法。

  2. 将实例变量作为参数传递给 mixin 方法,这将导致如下代码:

例子

self.do_something(self.text)

或者

@thing.do_something(@thing.text)

这对我来说看起来很讨厌,并且不符合面向对象的原则。

有没有其他方法可以做到这一点?,我担心吗?

4

3 回答 3

28

一般来说,避免让 mixins 访问成员变量:这是一种非常紧密的耦合形式,可能会使未来的重构变得不必要地困难。

一种有用的策略是让 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"

mixin 访问由包含类定义的“文本”访问器:

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 中使用通用和通用数据名称可能会导致冲突。在这种情况下,让 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

实例变量名称以 ruby​​ 开头,以 @ 开头,例如。@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 回答