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. linux常用命令:diff 命令

    diff 命令是 linux上非常重要的工具,用于比较文件的内容,特别是比较两个版本不同的文件以找到改动的地方.diff在命令行中打印每一个行的改动.最新版本的diff还支持二进制文件.diff程序的 ...

  2. html5设置全屏模式--开发游戏必备

    <!-- uc强制竖屏 --> <meta name="screen-orientation" content="portrait"> ...

  3. java程序初始化顺序

    使用场景:  在java程序中,当实例化对象时,对象的所在类的所有成员变量首先要进行初始化,只有当所有类成员完成初始化后, 才会调用对象所在类的构造函数创建对象. 初始化的原则: (1)静态对象优先于 ...

  4. Spring IOC 源码分析

    Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文 ...

  5. 20145216《网络对抗》逆向及BOF基础实践

    20145216<网络对抗>逆向及BOF基础实践 1 逆向及Bof基础实践说明 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件.该程序正常执行流程是:main调用foo函 ...

  6. C++类的静态成员变量初始化 Win32 API 定时器使用

    1.类的静态成员变量 .h 类声明入下 class A { public: static int x; }; .cpp文件 这样初始化. ; 2.定时器使用 1.SetTimer(HWND,UINT, ...

  7. [JavaScript] - form表单转json的插件

    jquery.serializejson.js 之前好像记录过,做项目又用到了再记下 在页面中引入js后就可以使用了 示例: //点击设置微信信息的form表单提交按钮后,执行wxConfig的con ...

  8. Unity3D学习笔记(一):Unity简介、游戏物体、组件和生命周期函数

    Project(工程.项目):工程是把游戏开发当前所需要的资源归类管理用的. Console控制台:日志.报错.调试,右上角,消息过滤 Assets:资源,存储游戏中一切用到的资源 Library:临 ...

  9. ajax用beforeSend自定义请求过程中客户端事件,提高用户体验

    本文为博主原创,未经允许不得转载: 在应用ajax的过程中,当我们再前台提交请求的时候,如果服务端响应事件比较长,就会导致需要等很长时间在前台才能接受到服务端返回的 响应结果,往往会导致用户重复点击按 ...

  10. 04_Flume多节点load_balance实践

    1.负载均衡场景 1)初始:上游Agent通过round_robin selector, 将event轮流发送给下游Collecotor1, Collector2 2)故障: 关闭Collector1 ...