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.

class Myclass
  def my_method
    @x = 1
    binding
  end
end
 
p b = Myclass.new.my_method
p b.eval("@x")
p eval("@x", b)

#结果一样 1

class Anotherclass
  def my_method
    # eval "self", TOPLEVEL_BINDING   #=> main
    eval("xx + yy", TOPLEVEL_BINDING)
  end
end
 
xx = 123
yy = 321
obj = Anotherclass.new
p obj.my_method #=> 444

TOPLEVEL_BINDING: 是预定义常量,表示顶层作用域的Binding对象。

6.24 Strings of Code Vs Blocks

eval只能执行代码字符串,instance_eval和class_eval可以执行代码字符串和block

array = [1,2,3]
x = 'd'
array.instance_eval("self[1] = x")
p array #=> [1, "d", 3]
尽量用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...

这种钩子方法写在模块里,用类方法的方式定义:

module M1
  def self.included(othermod)
    puts "m1 was included into #{othermod}"
  end
end
 
class C
  include M1
end
#=>m1 was included into C
 

另外一种方式钩住同一个事件,:#include方法可以覆写 ,但注意写在类C中。

我的理解类C.调用include方法,就是self.include。先是在自身调用覆写的include方法,然后用super关键字调用原始方法。

⚠️ 类方法是不能被继承的只能自己用。

⚠️ 类包含模块后默认是获得实例方法。除非用#extend

module M
  def hello
    puts "world"
  end
end
 
class C
  def self.include(mod)
    puts "Called: C.include(#{mod})"
    super  #因为覆写了include,所以需要用super调用原始的include功能,否则M不会被C包含
  end 
  include(M)
end
 
C.new.hello✅

类方法和钩子方法结合的技巧:P160页。

3-15 《元编程》第6章 3-16 hook method的更多相关文章

  1. 3-8《Ruby元编程》第二章对象模型

    <Ruby元编程> 第二章 对象模型 类定义揭秘inside class definitions: class关键字更像一个作用域操作符,核心作用是可以在里面随时定义方法. [].meth ...

  2. 一道模板元编程题源码解答(replace_type)

    今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是<C++模板元编程>第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: ...

  3. 初识C++模板元编程(Template Mega Programming)

    前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制. ...

  4. 3-11 《Ruby元编程》第4章block块 3-12

    第4章代码块blocks 基础知识 作用域:用代码块携带variables through scopes 通过传递block给instance_eval方法来控制作用域. 把block转换为Proc, ...

  5. C++模板元编程(C++ template metaprogramming)

    实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...

  6. 异步编程系列06章 以Task为基础的异步模式(TAP)

    p { display: block; margin: 3px 0 0 0; } --> 写在前面 在学异步,有位园友推荐了<async in C#5.0>,没找到中文版,恰巧也想提 ...

  7. atitit.元编程总结 o99

    atitit.元编程总结 o99.doc 1. 元编程(Metaprogramming) 1 2. 元编程的历史and发展 1 3. 元类型and元数据 1 4. 元编程实现方式 2 4.1. 代码生 ...

  8. C++ 元编程 —— 让编译器帮你写程序

    目录 1 C++ 中的元编程 1.1 什么是元编程 1.2 元编程在 C++ 中的位置 1.3 C++ 元编程的历史 2 元编程的语言支持 2.1 C++ 中的模板类型 2.2 C++ 中的模板参数 ...

  9. ES6中的元编程-Proxy & Reflect

    前言 ES6已经出来好久了,但是工作中比较常用的只有let const声明,通过箭头函数改this指向,使用promise + async 解决异步编程,还有些数据类型方法...所以单独写一篇文章学习 ...

  10. Python类元编程

    类元编程是指在运行时创建或定制类.在Python中,类是一等对象,因此任何时候都可以使用函数创建新类,而无需用class关键字.类装饰器也是函数,不过能够审查.修改,甚至把被装饰的类替换成其他类.元类 ...

随机推荐

  1. mysql数据安装问题汇总

    1.mysql安装冲突:conflicts with file from package 看到“conflicts”,是产生冲突了,文件“/usr/share/mysql/charsets/*”需要M ...

  2. Js基础知识4-函数的三种创建、四种调用(及关于new function()的解释)

    在js中,函数本身属于对象的一种,因此可以定义.赋值,作为对象的属性或者成为其他函数的参数.函数名只是函数这个对象类的引用. 函数定义 // 函数的三种创建方法(定义方式) function one( ...

  3. java异常复习

    如果有时学东西概念太多了,可以反着学,从结果到过程,从代码到概念,也许就不会那么枯燥了,比如学反射的时候. java异常复习 异常和错误的区别? 异常:程序或环境本身出现错误.(程序员可以捕获并处理) ...

  4. python模块-json、pickle、shelve

    json模块 用于文件处理时其他数据类型与js字符串之间转换.在将其他数据类型转换为js字符串时(dump方法),首先将前者内部所有的单引号变为双引号,再整体加上引号(单或双)转换为js字符串:再使用 ...

  5. CSS3实现小黄人动画

    转载请注明出处,谢谢! 每次看到CSS3动画就心痒痒想试一下,记得一个多月前看了白树哥哥的一篇博客,突然开窍,于是拿他提供的demo试了一下,感觉很棒!下图为demo提供的动画帧设计稿. 自己也想说搞 ...

  6. Python3基础 list 查看filter()返回的对象

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  7. Python3基础 函数 递归 阶乘与斐波那契数列

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  8. bootstrap的 附加导航Affix导航 (侧边窄条式 滚动监控式导航) 附加导航使用3.

    affix: 意思是粘附, 附着, 沾上. 因此, 附加导航就是 bootstrap的 Affix.js组件. bootstrap的 附加导航, 不是说导航分成主导航, 或者什么 副导航的 而是指, ...

  9. P3386 【模板】二分图匹配 -网络流版

    二分图匹配 题目背景 二分图 感谢@一扶苏一 提供的hack数据 题目描述 给定一个二分图,结点个数分别为n,m,边数为e,求二分图最大匹配数 输入输出格式 输入格式: 第一行,n,m,e 第二至e+ ...

  10. 【Map】Echarts之iphone销量地图的使用以及详细配置

    1.引入echarts库文件 <script charset="utf-8" type="text/javascript" language=" ...