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

Ruby 如何在mixin方法中访问实例变量?,ruby,module,methods,mixins,Ruby,Module,Methods,Mixins,如何在mixin方法中访问实例变量?我可以想出两种方法,但两种方法都有问题 让mixin方法像任何类方法一样直接访问实例变量,例如self.text。问题在于,它限制了mixin方法的使用位置,并强制进行混合的类使用特定方式命名的特定实例方法 将实例变量作为参数传递给mixin方法,这将产生如下代码: 范例 self.do_something(self.text) 或 在我看来,这看起来很糟糕,而且不符合面向对象的原则 还有其他方法吗?我担心的对吗?您可以在本模块中自己提供此实例方法,但必须小

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

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

  • 将实例变量作为参数传递给mixin方法,这将产生如下代码:

  • 范例

    self.do_something(self.text)
    

    在我看来,这看起来很糟糕,而且不符合面向对象的原则


    还有其他方法吗?我担心的对吗?

    您可以在本模块中自己提供此实例方法,但必须小心不要覆盖现有方法

    示例(在您正在混合的模块中):


    实例变量名在ruby中以@eg.
    @变量开始。您可以从包含的模块中使用此名称访问它们

    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
    

    一般来说,避免让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访问“text”访问器,该访问器由include类定义:

    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
    
    当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"
    

    通过这种方式,访问器在mixin的数据和include类的数据之间充当某种“阻抗匹配器”或“转换器”。

    谢谢Kylo,但这似乎仍然限制了mixin的使用方式。拉入它的类必须仍然有一个实例变量@text。
    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"