3-15 《元编程》第6章 3-16 hook method
Code That Writes Code
6.1 Coding your way to the weekend
6.2 Kernel#eval, Binding#eval
Binding:
Objects of class Binding(类Binding的对象)
encapsulate (密封)the execution context at some particular place in the code and retain this context for future use.
如果你想要一段已经执行的代码在今后反复使用,可以用Binding对象封装它。
The variables, methods, value of self
, and possibly an iterator block(迭代块) that can be accessed in this context are all retained.
变量,方法,自身的value,甚至迭代块都可以用Binding对象封装储存。
Binding objects can be created using Kernel#binding
eval(string [, filename [,lineno]]) → obj
Evaluates the Ruby expression(s) in string, in the binding's context.
Binding对象的eval方法,可以评估字符串内的Ruby表达式,并返回表达式的值。
If the optional filename and lineno parameters are present, they will be used when reporting syntax errors.
#结果一样 1
TOPLEVEL_BINDING: 是预定义常量,表示顶层作用域的Binding对象。
6.24 Strings of Code Vs Blocks
eval只能执行代码字符串,instance_eval和class_eval可以执行代码字符串和block
流行的做法是禁止使用eval方法,同时用Dynamic methods和Dynamic Dispatch替代
污染对象
Ruby把外部传入的对象标记为污染对象。Object#taint -> obj.
判断: #tainted? ->true/false
去掉污染 #untaint
谨慎使用安全级别p148页
可以使用proc {}.call 作为洁净室
6.3Hook Method:
Class#inherited是一个实例方法,当一个类被继承时,Ruby会调用这个方法,Class#inherited方法什么也不做,但程序员可以覆写它的行为,像这样的方法称为钩子方法。
inherited(subclass):Callback invoked whenever a subclass of the current class is created.
更多的钩子方法:
Module#included,#prepended,#method_added, #method_removed, #method_undefined (只对实例方法有用),#singleton_method_added...
这种钩子方法写在模块里,用类方法的方式定义:
另外一种方式钩住同一个事件,:#include方法可以覆写 ,但注意写在类C中。
我的理解类C.调用include方法,就是self.include。先是在自身调用覆写的include方法,然后用super关键字调用原始方法。
⚠️ 类方法是不能被继承的只能自己用。
⚠️ 类包含模块后默认是获得实例方法。除非用#extend
类方法和钩子方法结合的技巧:P160页。