有趣的Ruby-学习笔记4

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的类都会改变行为

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值