Ruby块
块,在我看来就是插入一段可变的函数
block_name{
statement1
statement2
..........
}
看起来不知道是什么,不过别急,继续往下看。
块函数通过yield来调用
yield 语句
yield英文就是 屈服,放弃,不知道为什么用这个单词,难道是 此处函数就放弃了控制权?
例子
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
def test
puts "在 test 方法内"
yield
puts "你又回到了 test 方法内"
yield
end
test {puts "你在块内"}
运行了这段后的效果是
在 test 方法内
你在块内
你又回到了 test 方法内
你在块内
在yield的部分运行了你调用时传入的块语句。
所以yield是不是看起来没啥用?继续往下看
yield可以带参数
您也可以传递带有参数的 yield 语句。下面是一个实例:
#!/usr/bin/ruby
# -*- coding: UTF-8 -*-
def test
yield 5
puts "在 test 方法内"
yield 100
end
test {|i| puts "你在块 #{i} 内"}
块和方法
如果方法的最后一个参数前带有 &,那么您可以向该方法传递一个块,且这个块可被赋给最后一个参数。如果 * 和 & 同时出现在参数列表中,& 应放在后面。
#!/usr/bin/ruby
def test(&block)
block.call
end
test { puts "Hello World!"}
是不是令你想起了javascript里面的回调函数?
结合上yield传参,可以实现传入一段回调函数,并且该回调函数中可以根据函数执行的过程中传入的不同参数做出不同的行为。
总算感觉块这个特性有点用了。。。
BEGIN 和 END 块
BEGIN和END块就像java中的拦截器,一个是before拦截器,一个是after拦截器
#!/usr/bin/ruby
BEGIN {
# BEGIN 代码块
puts "BEGIN 代码块"
}
END {
# END 代码块
puts "END 代码块"
}
# MAIN 代码块
puts "MAIN 代码块"
一个程序可以包含多个 BEGIN 和 END 块。BEGIN 块按照它们出现的顺序执行。END 块按照它们出现的相反顺序执行。当执行时,上面的程序产生产生以下结果:
BEGIN 代码块
MAIN 代码块
END 代码块
Ruby模块
模块(Module)是一种把方法、类和常量组合在一起的方式。模块(Module)为您提供了两大好处
- 模块提供了一个命名空间和避免名字冲突
- 模块实现了 mixin 装置
模块(Module)定义了一个命名空间,相当于一个沙盒,在里边您的方法和常量不会与其他地方的方法常量冲突。
- 模块类似与类,但有一下不同模块不能实例化
- 模块没有子类
- 模块只能被另一个模块定义
module Identifier
statement1
statement2
...........
end
模块常量命名与类常量命名类似,以大写字母开头。方法定义看起来也相似:模块方法定义与类方法定义类似。
例子
#!/usr/bin/ruby
# 定义在 trig.rb 文件中的模块
module Trig
PI = 3.141592654
def Trig.sin(x)
# ..
end
def Trig.cos(x)
# ..
end
end
require 语句
终于看到require语句了!没有require功能简直是不能写代码啊,所以结合上require,module功能是我看到最重要的功能了
实例
$LOAD_PATH << '.'
require 'trig.rb'
y = Trig.sin(Trig::PI/4)
注意这句话 $LOAD_PATH << '.' 这句话是把require的路径定到当前的文件路径,我刚开始require总是失败就是因为没有这句话
如果不想用 $LOAD_PATH 还可以使用 require_relative 方法
require_relative 'trig.rb'
y = Trig.sin(Trig::PI/4)
也可以!而且 我更喜欢 require_relative 因为更好记!
include 语句
您可以在类中嵌入模块。你肯定跟我会有一样的疑问:“可是,我都有require了为什么还要include?!”
假设以下代码写在 support.rb 里面
module Week
FIRST_DAY = "Sunday"
def Week.weeks_in_month
puts "You have four weeks in a month"
end
def Week.weeks_in_year
puts "You have 52 weeks in a year"
end
end
我们来嵌入一下
#!/usr/bin/ruby
$LOAD_PATH << '.'
require "support"
class Decade
include Week
no_of_yrs=10
def no_of_months
puts Week::FIRST_DAY
number=10*12
puts number
end
end
d1=Decade.new
puts Week::FIRST_DAY
Week.weeks_in_month
Week.weeks_in_year
d1.no_of_months
你会发现,
有没有那行 include Week 代码执行结果根本就没有区别!
那include有什么卵用呢?!
要解释include究竟有什么用,就要介绍一下 ruby 的 mixins 特性
Ruby 中的 Mixins
Ruby中并没有多重继承,取而代之的是Mixin。当你将模块include到类定义中,模块中的方法就被mix到了类里面
实例代码,看A, B 如何被mix到 Sample里面
module A
def a1
end
def a2
end
end
module B
def b1
end
def b2
end
end
class Sample
include A
include B
def s1
end
end
samp=Sample.new
samp.a1
samp.a2
samp.b1
samp.b2
samp.s1
include & require & load
原来include跟require有以下的区别(这边还要提到load方法)
- require不需要跟上后缀,会自动识别 xxx.rb
- require如果调用2次就会报错,如果要调用多次就用load,但是用load得写上文件后缀名
- require一般用于加载库文件,load一般用户加载配置文件
- include 用于把一个文件中的模块mix到类中
- include并不会把module的实例方法拷贝到类中,只是做了引用,包含module的不同类都指向了同一个对象。如果你改变了module的定义,即使你的程序还在运行,所有包含module的类都会改变行为