Ruby在没有显式包含声明的子类上执行self.included(base)方法?

我有一些从一个超类继承的类.
超类作为模块定义.模块内部是一个self.included(base)方法,用于设置一些实例变量.

所以这样的事情:

module MyModule
  def self.included(base)
    base.instance_variable_set("@my_instance_variable",{})
  end
end

class MySuperClass
  include MyModule
end

class ClassA < MySuperClass
end

class ClassB < MySuperClass
end

除非我在ClassA和ClassB中明确包含MyModule,否则我的实例变量将不会在这两个类中设置.

有没有办法确保模块self.included(base)方法在每个子类中执行而无需显式包含模块?因为它已经包含在超类中.

解决方法

类实例变量是类的私有.继承的类无法直接访问它们.这里有几种方法.

1.定义访问者

module MyModule
  def self.included(base)
    base.instance_variable_set :@my_instance_variable,{}
    base.extend ClassMethods
  end

  module ClassMethods
    def my_instance_variable
      # self is ClassA here,so we need to call superclass
      superclass.instance_variable_get :@my_instance_variable # => {}
    end
  end
end

class MySuperClass
  include MyModule
end

class ClassA < MySuperClass; end

ClassA.my_instance_variable # => {}

2.更多元编程

但是每次从你继承一个类时都会调用一个钩子.您可以在此处设置变量.看一下这个.

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

  module ClassMethods
    # make it a class method. It will be called on target classes later.
    def enhance klass 
      klass.instance_variable_set("@my_instance_variable",{})
    end
  end
end

class MySuperClass
  include MyModule

  # this hook will get called on 'class ClassA < MySuperClass`
  def self.inherited klass
    # set class instance var on child class
    enhance klass
  end
end

class ClassA < MySuperClass; end

ClassA.instance_variable_get '@my_instance_variable' # => {}

注意:在此示例中,每个继承的类都获得自己的类实例var(并且基类不会获得一个).这可能更适合您的情况,可能不适合.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...