这里列出了《Ruby 元编程》介绍的所用法术
环绕别名 Around Alias
从一个重新定义的方法中调用原始的、被重命名的版本
class String
alias_method :old_reverse, :reverse
def reverse
"x#{old_reverse}x"
end
end
'abc'.reverse # => 'xcbax'
白板类 Blank Slate
移除一个对象中的所有方法,以便吧他们转换成幽灵方法
class C
def method_missing(name, *args)
"#{name} is a ghost method"
end
end
obj = C.new
obj.to_s # => "#<C:...>"
class B < BasicObject
def method_missing(name, *args)
"#{name} is a ghost method"
end
end
blank_slate = B.new
blank_slate.to_s # => "to_s is a ghost method"
类扩展 Class Extension
通过向类的单件类中加入模块来定义类方法,是对象扩展的一个特例
class C
end
module M
def a_method
'a method'
end
end
class << C
include M
end
C.a_method # => 'a method'
类实例变量 Class Instance Variable
在一个Class对象的实例变量中存储类级别的状态
class C
@my_class_instance_variable = 'some value'
def self.class_attribute
@my_class_instance_variable
end
end
C.class_attribute # => 'some value'
类宏 Class Macro
在类定义中使用方法
class C
end
class << C
def a_method(arg)
"a_method(#{arg} called)"
end
end
class C
a_method :x # => "a_method(x) called"
end
洁净室 Clean Room
使用一个对象作为执行一个代码块的环境
class CleanRoom
def a_userful_method x
x * 2
end
end
CleanRoom.new.instance_eval { a_userful_method(3) } # => 6
代码处理器 Code Processor
处理从外部活的的代码字符串
File.readlines('a_file_containing_lines_of_ruby.txt').each do |line|
puts "#{line.chomp} ==> #{eval(line)}"
end
# => 1 + 1 ==> 2
# => Math.log10(100) ==> 2.0
上下文探针 Context Probe
执行一个代码块来获取一个对象上下文中的信息
class C
def initialize
@x = 'a private instance variable'
end
end
obj = C.new
obj.instance_eval { @x } # => 'a private instance variable'
延迟执行 Deferred Evaluation
在 proc 或 lambda 中存储一段代码及其上下文,用于以后执行
class C
def store(&block)
@my_code_capsule = block
end
def execute(*args)
@my_code_capsule.call(*args)
end
end
obj = C.new
obj.store { $X = 1 }
$X = 0
obj.execute
$X # => 1
动态派发 Dynamic Dispatch
在运行是决定调用哪个方法
method_to_call = :reverse
obj = 'abc'
obj.send(method_to_call) # => 'reverse'
动态方法 Dynamic Method
在运行是决定怎样定义一个方法
class C
end
C.class_eval do
define_method :a_method do
'a dynamic method'
end
end
obj = C.new
c.a_method # => 'a dynamic method'
动态代理 Dynamic Proxy
把不能对应某个方法名的消息转发给另外一个对象
class MyDynamicProxy
def initialize(target)
@target = target
end
def method_missing(name, *args, &block)
"result: #{@target.send(name, *args, &block)}"
end
end
obj = MyDynamicProxy.new('a string')
obj.reverse # => 'result: gnirts a'
扁平作用域 Flat Scope
使用闭包在两个作用域之间共享变量
class C
def an_attribute
@attr
end
end
obj = C.new
a_variable = 100
obj.instance_eval do
@attr = a_variable
end
obj.an_attribute # => 100
幽灵方法 Ghost Method
响应一个没有关联方法的消息
class C
def method_missing(name, *args)
name.to_s.reverse
end
end
obj = C.new
obj.my_ghost_method # => 'dohtem_tsohg_ym'
钩子方法 Hook Method
复写一个方法来截获对象模型事件
$INHERITORS = []
class C
def self.inherited(subclass)
$INHERITORS << subclass
end
end
class D < C
end
class E < D
end
class F < E
end
$INHERITORS # => [D, E ,F]
内核方法 Kernel Method
在Kernel模块中定义一个方法,使得所有对象都可使用
module Kernel
def a_method
'a kernel method'
end
end
a_method # => 'a kernel method'
惰性实例变量 Lazy Instance Variable
等第一次访问一个实例变量时才对它进行初始化
class C
def attribute
@attribute = @attribute || 'some value'
end
end
obj = C.new
obj.attribute # => 'some value'
拟态方法 Mimic Method
把一个方法伪装成另外一种语言构件
def BaseClass name
name == 'string' ? String : Object
end
class C < BaseClass 'string' # 一个看起像类的方法
attr_accessor :an_attribute # 一个看起像关键字的方法
end
obj = C.new
obj.an_attribute = 1 # 一个看起像属性的方法
猴子打补丁 Monkeypatch
修改已有类的特性
'abc'.reverse # => 'cba'
class String
def reverse
'override'
end
end
'abc'.reverse # => 'override'
命名空间 Namespace
在一个模块中定义常量,以防止命名冲突
module MyNamespace
class Array
def to_s
'to_a method in array of the my namespace'
end
end
end
Array.new.to_s # => []
MyNamespace::Array.new.to_s # => 'to_a method in array of the my namespace'
空指针保护 Nil Guard
用’ | ‘操作符覆写一个空引用 |
x = nil
y = x || 'a value' # => 'a value'
对象扩展 Object Extension
通过一个对象的单件类混入模块来定义单件方法
obj = Object.new
module M
def a_method
'a singleton method in M'
end
end
class << obj
include M
end
obj.a_method # => 'a singleton method'
打开类 Open Class
修改已有的类
class String
def a_method
'a method'
end
end
'abc'.a_method # => 'a method'
下包含包装器 Prepended Wrapper
调用一个用 prepend 方式覆写的方法
module M
def reverse
"x#{super}x"
end
end
String.class_eval do
prepend M
end
'abc'.reverse # => 'xcbax'
细化 Refinement
为类打补丁,作用范围仅到文件结束,或仅限于包含模块的作用域中
module MyRefinement
refine String do
def reverse
'refinement reverse'
end
end
end
'abc'.reverse # => 'cba'
using MyRefinement
'abc'.reverse # => 'refine reverse'
细化封装器 Refinement Wrapper
在细化中调用非细化的方法
module StringRefinement
refine String do
def reverse
"x#{super}x"
end
end
end
using StringRefinement
'abc'.reverse # => 'xcbax'
沙盒 Sandbox
在一个安全的环境中执行未授权的代码
def sandbox &code
proc do
$SAFE = 2
yield
end.call
end
begin
sandbox { File.delete 'a_file' }
rescue Exception => ex
ex # =>
end
作用域门 Scope Gate
用class, module 或 def 关键字来隔离作用域
a = 1
defined? a # => 'local-variable'
module MModule
b = 1
defined? a # => nil
defined? b # => 'local-variable'
end
defined? a # => 'local-variable'
defined? b # => nil
Self Yield
把self传给当前代码块
class Person
attr_accessor :name, :surname
def initialize
yield self
end
end
joe = Person.new do |person|
person.name = 'Joe'
person.surname = 'Smith'
end
共享作用域 Shared Scope
在同一个扁平作用域的多个上下文中共享变量
lambda do
shared = 10
self.class_eval do
defined_method :counter do
shared
end
defined_method :down do
shared -= 1
end
end
end.call
counter # => 10
3.times { down }
counter # => 7
单件方法 Singleton Method
在一个对象上定义一个方法
obj = 'abc'
class << obj
def obj_singleton_method
'x'
end
end
obj.obj_singleton_method # => 'x'
代码字符串 String of Code
执行一段表示ruby代码的字符串
string_of_code = '1 + 1'
eval(string_of_code) # => 2
符号到Proc Symbol To Proc
把一个调用单个方的块转换为一个符号
(1..6).map(&:even?) # => [false, true, false, true, false, true]