代码之家  ›  专栏  ›  技术社区  ›  dangerousdave

如何访问mixin方法中的实例变量?

  •  14
  • dangerousdave  · 技术社区  · 16 年前

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

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

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

    例子

    self.do_something(self.text)
    

    @thing.do_something(@thing.text)
    

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

    还有别的办法吗?我有权关心吗?

    3 回复  |  直到 11 年前
        1
  •  23
  •   Wayne Conrad    16 年前

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

    一个有用的策略是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访问由include类定义的“text”访问器:

    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"
    

    如果你需要在这节课上加入混音器怎么办?

    class Foo
    
    def initialize
      @text = "Text that has nothing to do with the mixin"
    end
    
    end
    

    当include类使用相同的名称时,在mixin中使用通用和通用数据名称可能会导致冲突。在这种情况下,让mixin查找不常用名称的数据:

    module Mixin
    
      def do_something
        p mixin_text
      end
    
    end
    

    并让include类定义适当的访问器:

    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"
    

    通过这种方式,存取器充当混入数据和包含类数据之间的“阻抗匹配器”或“转换器”。

        2
  •  2
  •   johannes    16 年前

    实例变量名以ruby开头,并带有@eg。 @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
    
        3
  •  1
  •   Kylo    16 年前

    您可以在这个模块中自己提供这个实例方法,但是必须注意不要覆盖现有的方法。

    示例(在混合模块中):

    def text
        @text ||= ""
    end