我有一些从一个超类继承的类.
超类作为模块定义.模块内部是一个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(并且基类不会获得一个).这可能更适合您的情况,可能不适合.