我有一些继承自一个超类的类。 超类作为模块定义。模块内部是一个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)方法在每个子类中执行而无需显式包含模块?因为它已经包含在超类中。
答案 0 :(得分:14)
类实例变量对类是私有的。继承的类无法直接访问它们。这里有几种方法。
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 # => {}
但每次从你继承一个类时都会调用一个钩子。您可以在此处设置变量。看看这个。
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(并且基类不会获得一个)。这可能更适合您的情况,可能不适合。