最近在项目代码里看到了 prepend 的用法, 读了文档, 基本明白了它的用法; 但是对于说它是为了解决之前 alias_methods 的问题的这部分讨论还没看明白(可能是我没怎么用过alias_method)
在我的理解中这几点比较关键:
- 和ruby其他的hook(
inheritedincluded…)类似, prepend 也有自己的hook:prepended - prepend把模块里的方法插入到方法查找链里面, 可以覆盖当前类里的方法定义
 
示例
- 定义一个普通的类, run方法会遍历并打印参数, 然后返回结果
 
1  | class Service  | 
- 如果给它
prepend一个moduleServiceDebugger, 里面定义一个同名的方法, 这个模块里的方法定义会覆盖Service里的方法定义 
1  | module ServiceDebugger  | 
- module 
ServiceDebugger里面可以调用super方法, 调用原始定义的方法, 类似around_hook里的yield 
1  | module ServiceDebugger  | 
可以用这种机制, 在不修改原有代码的情况下, 增强原有的方法, 例如 增加日志; super前的代码类似于
before_hook, 之后的代码类似于after_hook此外, 可以在被prepend的模块里定义
prepended, 里面实现一些自动触发的行为
1  | module ServiceDebugger  | 
是魔法吗? 不确定; 不知道其他语言有没有这么多hook 和灵活的用法
2022-07-09 09:47:43 update
不是魔法, hook的本质大概是在模块/类的生命周期中 提前定义好”如果存在则会被调用的代码块”, 从外部看来就是hook了
用这种视角来看, 其他语言肯定也可以实现
核心大概是: “生命周期” 和 “封装”
很好例子就是 activerecord 里的 “The Object Life Cycle”
清晰的定义 配合良好的封装, 使得activerecord的hook使用起来很方便