201707《Ruby元编程》

元编程不过是编程——经典必读

作用域(绑定)

改变作用域的关键字, 分别是module,class和def。我们称为作用域的门(scope gate)

instance_eval以实例作用域执行代码

class_eval以类定义作用域执行代码

Kernel#eval方法,当前上下文中直接执行代码字符串

instance_eval class_eval
对象 单例方法 --
类名(元类对象) 类方法 实例方法

表格是不精准、不完备的表达,instance_eval、class_eval使用时需要注意区分调用对象

打破作用域门的方式

  • 类定义使用 Class.new 替换
  • 模块定义使用 Module.new 替换
  • 方法定义使用 define_method 替换

对象模型图

七条规则

  1. 只有一种对象——要么是普通对象,要么是模块
  2. 只有一种模块——可以是一个普通模块、一个类或者一个单件类
  3. 只有一种方法,它存在于一个模块中——通常是在一个类中
  4. 每个对象(包括类)都有自己的“真正的类”——要么是一个普通类,要么是一个单件类
  5. 除了BasicObject类没有超类外,每个类有且只有一个祖先——要么是一个类,要么是一个模块。这意味着任何类只有一条向上的、直到BasicObject的祖先链。
  6. 一个对象的单件类的超类是这个对象的类;一个的单件类的超类是这个类的超类的单件类
  7. 调用一个方法时,Ruby先向右迈一步,进入接收者真正的类,然后向上进入祖先链。这就是Ruby查找方法的方式

法术手册

  • 环绕别名:加一层包装,A => A-B-_A
  • 白板类:移除一个类的所有方法,以便把它们转换为幽灵方法
  • 类扩展:通过向类的单件类中加入模块定义类方法,是对象扩展的一个特例
  • 类实例变量:Class对象的实例中存储类级别的状态
  • 类宏:在类定义中使用方法
  • 洁净室:使用一个对象作为执行一个代码块的环境Cleanroom.new.instance_eval{fun()}
  • 代码处理器:处理从外部获得的代码字符串
  • 上下文探针:执行一个代码块来获取一个对象上下文中的信息
  • 延迟执行:在proc和lambda中存储一段代码及其上下文,用于以后执行
  • 动态派发:在运行时决定调用哪个方法
  • 动态方法:在运行时决定怎样定义一个方法
  • 动态代理:把不能对应某个方法名的消息转发给另外一个对象
  • 扁平作用域:
  • 幽灵方法:响应一个没有关联方法的消息
  • 钩子方法:覆写一个方法来截获对象模型事件
  • 内核方法:在Kernel模块中定义一个方法,使得所有对象都可使用
  • 惰性实例变量:等第一次访问时才进行初始化@a ||= "str"
  • 拟态方法:把一个方法伪装成另外一个语言构件
  • 猴子补丁:修改已有类的特性
  • 命名空间:在一个模块中定义常量,以防止命名冲突
  • 空指针保护:x=nil;y = x || ‘str‘
  • 对象扩展:通过给一个对象的单件类混入模块来定义单件方法
  • 打开类:修改已有的类
  • 下包含包装器:调用一个用prepend方式覆写的方法
  • 细化:refine为类打补丁,作用范围仅到文件结束或模块作用域
  • 细化封装器:在细化中调用非细化的方法
  • 沙盒:$SAFE在一个安全环境中执行未授信代码
  • 作用域门:class、def、module
  • Self Yield:把self传给当前代码块
  • 共享作用域:在同一个扁平作用域的多个上下文中共享变量
  • 单件方法:在一个对象上定义一个方法
  • 代码字符串:
  • 符号到Proc:把一个调用单个方法的块转换为一个符号
时间: 2024-12-09 02:53:44

201707《Ruby元编程》的相关文章

Ruby 元编程

Ruby 语言在抽象层面有了元编程支持,功能相当强大,如果业务模型有很大的相似性,相信元编程会让你节省大量代码. 举一个小例如下,(这里只是使用了一个class_eval , 还有instance_eval, module_eval, Function.parameters等大量方法可以调用) 比如 ,根据业务需求,需要创建多个有相似方法名的类, 比如方法都命令为 include_xxx, append_xxx, delete_xxx,  xxxs等 xxx 为具体的业务类. 那么可以设计如下一

3-8《Ruby元编程》

<Ruby元编程> 第二章 对象模型 类定义揭秘inside class definitions: class关键字更像一个作用域操作符,核心作用是可以在里面随时定义方法. [].methods.grep(/^re/):调用 出Array的所有以re开头的method. Monkeypatch:涉及全局修改,定义某个方法前应该仔细检查该类是否已有同名的方法. 实例对象存放在对象中,方法存放在类中. 类的真相:类本身也是对象.Ruby允许在运行时修改类的信息. Class.instance_me

读《Ruby 元编程》

通过许多法术,Ruby 有的编程技巧来实现很多巧妙的编程: 数组参数 环绕别名 白板 类扩展 类扩展混入 类实例变量 类宏 洁净室 代码处理器 上下文探针 延迟执行 动态派发 动态方法 动态代理 扁平作用域 幽灵方法 钩子方法 内核方法 惰性实例变量 拟态方法 猴子打补丁 -- 上面的高级些的技巧,来实现更简洁的编程(只是指总行数),方便修改上. 一个文件成千行,还是存在的. 要看懂,还要了解些 Ruby 的基础才行的. 推荐 2星

Ruby元编程::对象模型

对象由一组实例变量和一个类的引用组成. 对象的方法存在于对象所属的类中(从类的角度看,它们叫做实例方法). 类本身是Class类的对象.类的名字不过是一个常量而已. Class类是Module的子类.一个模块基本上是由一组方法组成的包.类除了具有模块的特性之外,还可以被实例化(通过new()方法)及被组织为层次结构(通过它的super-class()方法). 常量像文件系统一样,是按照树形结构组织的.其中模块和类的名字扮演目录的角色,其他普通的常量则扮演文件的角色. 每个类都有一个祖先链,这个链

ruby元编程——编写代码的代码

Kernel#eval()方法,可以直接执行ruby代码字符串 (1)Kernel#binding()方法用来捕获当前作用域返回一个Binding对象,Binding对象表示一个完整的作用域 (2)eval()可以接受两个参数,第一个是代码字符串,第二个是Binding对象,代码会在传入的作用域中执行(*eval()家族都可以) (3)Ruby还提供了一个名为TOPLEVEL_BINDING的预定义常量,他表示顶级作用域的Binding对象.可以在程序的任何地方访问这个顶级作用域 (4) eva

201706 Ruby 基础 & 元编程

yield 所有的"方法(methods)"隐式跟上一个"块(block)"参数. 块参数也可以明确给定,形式就是在参数前面加一个"&",比如 def fn(arg1, arg2, &block) end,其中的 &block 就是明确给定的块参数. 块参数的动作,可以通过调用 call() 方法执行,还可以用 yield 来执行 -- yield 其实就是一个语法糖. 所以以下几种写法常常是等价的: #method re

C++模板元编程 - 2 模仿haskell的列表以及相关操作

这是昨天和今天写的东西,利用C++的可变模板参数包以及包展开,模式匹配的一些东西做的,感觉用typename...比轮子叔那个List<A,List<B, List<C, D>>>的设计要好看不少. List有一个很巧妙的继承,只有那么做才能使用类似于List<>::Rest的写法,直接定义成template<typename T, typename... TArgs>List是不行的. Change这里可以给一个args...换另一个包装,这里

《Effective C++》:条款48:认识template元编程

Template metaprogramming(TMP,模板元编程)是编写template-based C++程序,编译的过程.template metaprogramming是用C++写的模板程序,编译器编译出具体化的过程.也就是说,TMP程序执行后,从templates具体化出来C++源码,不再是模板了. TMP有两个作用,一是它让某些事更容易.例如编写STL容器,使用模板,可是存放任何类型元素.二是将执行在运行期的某些工作转移到了编译期.还有一个结果是使用TMP的C++程序可能在其他方面

C++拾遗--模板元编程

C++拾遗--模板元编程 前言 模板元是用于递归加速的,把运行期的函数调用变到编译期进行代码展开,类似于内联函数.下面看一个实例:斐波那契数列第n项求解. 模板元编程 #include <iostream> #include <ctime> using namespace std; //递归法 int fib(int n) { if (n < 0) return 0; if (n == 1 || n == 2) return 1; return fib(n - 1) + fi