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

前端之家收集整理的这篇文章主要介绍了Ruby在没有显式包含声明的子类上执行self.included(base)方法?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一些从一个超类继承的类.
超类作为模块定义.模块内部是一个self.included(base)方法,用于设置一些实例变量.

所以这样的事情:

  1. module MyModule
  2. def self.included(base)
  3. base.instance_variable_set("@my_instance_variable",{})
  4. end
  5. end
  6.  
  7. class MySuperClass
  8. include MyModule
  9. end
  10.  
  11. class ClassA < MySuperClass
  12. end
  13.  
  14. class ClassB < MySuperClass
  15. end

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

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

解决方法

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

1.定义访问者

  1. module MyModule
  2. def self.included(base)
  3. base.instance_variable_set :@my_instance_variable,{}
  4. base.extend ClassMethods
  5. end
  6.  
  7. module ClassMethods
  8. def my_instance_variable
  9. # self is ClassA here,so we need to call superclass
  10. superclass.instance_variable_get :@my_instance_variable # => {}
  11. end
  12. end
  13. end
  14.  
  15. class MySuperClass
  16. include MyModule
  17. end
  18.  
  19. class ClassA < MySuperClass; end
  20.  
  21. ClassA.my_instance_variable # => {}

2.更多元编程

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

  1. module MyModule
  2. def self.included(base)
  3. base.extend ClassMethods
  4. end
  5.  
  6. module ClassMethods
  7. # make it a class method. It will be called on target classes later.
  8. def enhance klass
  9. klass.instance_variable_set("@my_instance_variable",{})
  10. end
  11. end
  12. end
  13.  
  14. class MySuperClass
  15. include MyModule
  16.  
  17. # this hook will get called on 'class ClassA < MySuperClass`
  18. def self.inherited klass
  19. # set class instance var on child class
  20. enhance klass
  21. end
  22. end
  23.  
  24. class ClassA < MySuperClass; end
  25.  
  26. ClassA.instance_variable_get '@my_instance_variable' # => {}

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

猜你在找的Ruby相关文章