一. 代码块的基本调用
ex1:
def test_method(a, b)
a + yield(a, b)
end
puts test_method(1, 2){|x, y| (x + y)*3}
test_methd接受一个代码块,yield处理代码块的调用位置,而且代码块是必须传的
ex2:
def test_method2(a, b)
a + (block_given? ? yield(a, b) : b)
end
puts test_method2(1, 2)
puts test_method2(1, 2){|x, y| (x + y)*3}
test_method2调用的时候,可以传递一个代码块,也可以不传递,方法内部做了判断(block_given?)
ex3:
def test_method3(a, b, &block)
a + (block ? yield(a, b) : b)
end
puts test_method3(1, 2)
puts test_method3(1, 2){|x, y| (x + y)*3}
test_method3显示的接受block参数,当使用&时,说明接受一个代码块
二. 变量的作用域
1. 闭包:代码块可以一直带着局部绑定, 并一直使用他们
def test_method5(a, &block)
a + yield(a)
end
x = 1
puts test_method5(2){|y| (x + y)*3}
x是被绑定的
2. 作用域门: 打开或者关闭一个作用域的地方
类定义:
模块定义:
方法:
3. 扁平作用域:
使得变量穿过作用域门(方法调用)
a = 1
MyClass = Class.new do
puts a
define_method :my_method do
puts a
end
end
MyClass.new.my_method
4. 共享作用域
instance_eval(BasicObject#instance_eval) 在对象的上下文执行,可以访问类的内部
class Test
private
def t1
puts "i am private!"
end
end
Test.new.instance_eval do
t1
end
这里可以直接访问 t1 方法, t1甚至是private 方法
另外还有instance_exec 可以传递参数到调用对象的内部。
三. 可调用对象
1. proc对象创建
p1 = Proc.new {|x| x + 1}
puts p1.call(1)
p2 = proc{|x| x + 1}
puts p2.call(1)
l1= lambda{|x| x + 1}
puts l1.call(1)
l2 = ->(x) {x + 1}
puts l2.call(1)
四. DSL
1. ruby 本身支持中文名字做方法名字
def 哈哈
puts "我在笑.... 哈哈"
end
哈哈
上面的代码可以直接调用哈哈这个方法
2. 汉语编程:
def 发生了(event)
yield(event)
end
发生了("爸爸来了") { |event| puts "#{event}: 我要写作业了" }