Ruby 内置了一些钩子 ( hook ) 方法,允许我们动态操作类,模块和对象。下面列出了一些最重要的钩子方法
Module#included
Module#extended
Module#prepended
Class#inherited
included, extended 和 prepended 三个模块级别的钩子方法
但一个模块被包含 ( included ) 、 扩展 ( extended ) 或预先前置在另一个模块或类中时,就会自动调用该模块下的这些钩子方法。
因为它们的工作模式类似,因此我们这里只以 included
钩子方法为例。
module Commentable def self.included(commentable_entity) puts "The #{commentable_entity} entity now accepts comments !" end end class MediumPost include Commentable end
运行结果如下
The MediumPost entity now accepts comments !
这些钩子方法允许我们为钩子所在的模块或类添加新方法或新属性。
这个机制实际上是由 ActiveSupport::Concern
模块使用的。
对于 Module#extended
和 Module#prepended
钩子方法,实现也非常相似
Class#inherited
当一个类定义了 Class#inherited
方法时,任何一个该类的子类被创建时就会自动调用该方法
当我们想要在每个子类的类定义中定义变量或类属性 ( class_attribute ) 时,此钩子方法非常方便
class User def self.inherited(user_type) puts "#{user_type} is a kind of user" end end class Tenant < User end
运行结果如下
Tenant is a kind of user
最显著的应用场景是:ActiveRecord::Core
模块对 initialize_find_by_cache
类方法的作用
总结
钩子相关方法可以非常方便地对类和模块进行操作。但是,当它们修改模块/类蓝图时,会引起一些不需要的副作用,如祖先类方法覆盖等
目前尚无回复