2010-02-19 46 views
13

如何在mixin方法中访问实例变量?我可以想到2种方法,但都显得有问题。如何访问mixin方法中的实例变量?

  1. 让mixin方法直接访问实例变量,就像任何类方法一样,比如self.text。问题在于它对mixin方法的使用位置施加了限制,并强制类进行混合,以特定方式命名特定的实例方法。

  2. 传递实例变量作为参数的混入的方法,这将导致这样的代码:

例如

self.do_something(self.text) 

@thing.do_something(@thing.text) 

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

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

回答

21

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

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

通过这种方式,存取作为排序混音输入数据和包含类别数据之间的“阻抗匹配器”或“翻译器”。

+0

谢谢韦恩,你真的清除了这一点。 – dangerousdave 2010-02-19 20:54:03

1

您可以在此模块中提供这种情况下你自己的方法,但你必须要小心,不要覆盖现有的方法

例(模块你是混合):

def text 
    @text ||= "" 
end 
+1

感谢Kylo,但这似乎仍然限制了mixin的使用方式。拉入它的类必须仍然有一个实例变量@text。 – dangerousdave 2010-02-19 12:25:44

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 

如果您wan't访问@t当它不是在你的类中定义之前,你可以这样来做

module M 
    def t 
    instance_variable_defined?("@t") ? @t : nil 
    end 
end