Ruby 获取对模块中定义的类变量的访问权限

Ruby 获取对模块中定义的类变量的访问权限,ruby,oop,rspec,Ruby,Oop,Rspec,因此,虽然我完全反对以这种方式扩展现有类,但有时(黑客攻击rspec)有必要执行以下操作: module MyModule module ClassMethods def define_something(name) @@names ||= [] @@names << name end end def self.included(base) base.extend ClassMethods end def all_n

因此,虽然我完全反对以这种方式扩展现有类,但有时(黑客攻击
rspec
)有必要执行以下操作:

module MyModule
  module ClassMethods
    def define_something(name)
      @@names ||= []
      @@names << name
    end
  end
  def self.included(base)
    base.extend ClassMethods
  end
  def all_names
    @@names
  end
end
class Example
  include MyModule
  define_something "one"
  define_something "two"
end
Example.new.all_names
我理解这一点,因为在编写
MyModule::ClassMethods
时,我们正在处理实例而不是类(而不是
self.
),所以我尝试:

module MyModule
  module ClassMethods
    def define_something(name)
      @names ||= []
      @names << name
    end
  end
  def self.included(base)
    base.extend ClassMethods
  end
  def all_names
    @@names
  end
end
class Example
  include MyModule
  define_something "one"
  define_something "two"
end
Example.new.all_names
模块MyModule
模块类方法
定义某物(名称)
@姓名| |=[]

@名称从设计角度来看,通常最好避免使用实例变量引用跨越类/实例行。这通常更清楚:

module MyModule
  module ClassMethods
    def define_something(name)
      self.defined_somethings << name
    end

    def defined_somethings
      @_my_module_names ||= []
    end
  end

  def self.included(base)
    base.extend ClassMethods
  end

  def all_names
    self.class.defined_somethings
  end
end

class Example
  include MyModule
  define_something "one"
  define_something "two"
end

Example.new.all_names.inspect
#=> ["one","two"]
模块MyModule
模块类方法
定义某物(名称)
自我定义的东西[“一”、“二”]
在这里,我注意创建了一个具有详细名称的类级实例变量。调用它
@name
可能会使它与包含此模块的类定义的变量发生冲突。请记住,在设计mixin代码时,您是一位客人,需要格外礼貌

类类型实例变量,如
@@name
,有时很麻烦,因为它们最终可能跨越继承链,具体取决于它们的使用方式。定义方法意味着您可以在链中的任何点重写它,这是共享变量不可能做到的


换句话说,将实例的类视为一个单独的对象,并进行明确、定义良好的方法调用以保持这种分离。

从设计角度来看,通常最好避免使用实例变量引用跨越类/实例行。这通常更清楚:

module MyModule
  module ClassMethods
    def define_something(name)
      self.defined_somethings << name
    end

    def defined_somethings
      @_my_module_names ||= []
    end
  end

  def self.included(base)
    base.extend ClassMethods
  end

  def all_names
    self.class.defined_somethings
  end
end

class Example
  include MyModule
  define_something "one"
  define_something "two"
end

Example.new.all_names.inspect
#=> ["one","two"]
模块MyModule
模块类方法
定义某物(名称)
自我定义的东西[“一”、“二”]
在这里,我注意创建了一个具有详细名称的类级实例变量。调用它
@name
可能会使它与包含此模块的类定义的变量发生冲突。请记住,在设计mixin代码时,您是一位客人,需要格外礼貌

类类型实例变量,如
@@name
,有时很麻烦,因为它们最终可能跨越继承链,具体取决于它们的使用方式。定义方法意味着您可以在链中的任何点重写它,这是共享变量不可能做到的

换句话说,将实例的类视为一个单独的对象,并进行明确的、定义良好的方法调用以保持这种分离

module MyModule
  module ClassMethods
    def define_something(name)
      @names ||= []
      @names << name
    end
  end
  def self.included(base)
    base.extend ClassMethods
  end
  def all_names
    self.class.instance_variable_get(:@names)
  end
end
class Example
  include MyModule
  define_something "one"
  define_something "two"
end

Example.new.all_names
模块MyModule
模块类方法
定义某物(名称)
@姓名| |=[]
@名称尝试以下方法

module MyModule
  module ClassMethods
    def define_something(name)
      @names ||= []
      @names << name
    end
  end
  def self.included(base)
    base.extend ClassMethods
  end
  def all_names
    self.class.instance_variable_get(:@names)
  end
end
class Example
  include MyModule
  define_something "one"
  define_something "two"
end

Example.new.all_names
模块MyModule
模块类方法
定义某物(名称)
@姓名| |=[]

@名称
@
@
完全不同。无论您是在类上下文还是实例上下文中,都不能使用
@
访问
@
变量,反之亦然。
@
@
是完全不同的。无论是在类上下文还是实例上下文中,都不能使用
@
访问
@
变量,反之亦然。