Ruby 模块 (Module)
模块 (Module) 是一种把方法、类和常量组合在一起的方式。
模块 (Module) 定义了一个命名空间,相当于一个沙盒,在里边的方法和常量不会与其它地方的方法常量冲突
模块(Module)带来了两大好处:
- 模块提供了一个 命名空间 和避免名字冲突
- 模块实现了 mixin 装置
模块类似与类,但有一下不同:
- 模块不能实例化
- 模块没有子类
- 模块只能被另一个模块定义
Ruby 模块语法
Ruby 语言中的模块定义语法格式如下
module <ModuleName> statement1 statement2 ........... end
- 模块中的常量命名与类常量命名类似,以大写字母开头
- 模块中的方法定义看起来和类也相似
- 可以使用模块名称和两个冒号来引用一个常量
范例
hello.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: hello.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. module Hello PI = 3.141592654 def Hello.sin(x) # .. end def Hello.cos(x) # .. end end
Ruby 语言允许定义多个函数名称相同但是功能不同的模块
quick.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: quick.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. module Quick VERY_BAD = 0 BAD = 1 def Quick.sin(badness) # ... end end
可以像定义类方法一样,在模块中定义一个方法时,可以指定在模块名称后跟着一个点号,点号后跟着方法名
Ruby require 语句
require 语句用于加载模块
如果一个第三方的程序想要使用任何已定义的模块,可以使用 Ruby require 语句来加载模块文件
require 语法格式
require filename
文件扩展名 .rb 不是必需的
范例
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: main.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. $LOAD_PATH << '.' require 'quick.rb' require 'hello' y = Quick.sin(Trig::PI/4) wrongdoing = Hello.sin(Moral::VERY_BAD)
使用 $LOAD_PATH << '.' 让 Ruby 知道必须在当前目录中搜索被引用的文件。 如果不想使用 $LOAD_PATH,那么您可以使用 require_relative 来从一个相对目录引用文件
注意
文件包含相同的函数名称。所以,这会在引用调用程序时导致代码模糊,但是模块避免了这种代码模糊,可以使用模块的名称调用适当的函数。
Ruby include 语句
Ruby 语言允许在类中嵌入模块
Ruby 语言提供了 include 语句用来在类中嵌入模块
include 语法格式如下
include modulename
注意
如果模块是定义在一个单独的文件中,那么在嵌入模块之前就需要使用 require 语句引用该文件
范例
week.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: week.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. 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
现在,可以在类中引用该模块
main.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: main.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. $LOAD_PATH << '.' require "week" 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
运行以上 Ruby 范例,输出结果如下
$ ruby main.rb Sunday You have four weeks in a month You have 52 weeks in a year Sunday 120
Ruby 中的 Mixins
在继续阅读本节之前,你需要初步了解具备面向对象的概念
当一个类可以从多个父类继承类的特性时,该类显示为多重继承
Ruby 不直接支持多重继承,但是 Ruby 的模块(Module)有另一个神奇的功能。它消除了多重继承的需要,提供了一种名为 mixin 的机制
Ruby 语言没有真正实现多重继承机制,而是采用 mixin 机制作为替代品
将模块 include 到类定义中,模块中的方法就 mix 进了类中
范例
a.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: a.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. module A def a1 end def a2 end end
b.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: b.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. module B def b1 end def b2 end end
hello.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: hello.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. $LOAD_PATH << '.' require "a" require "b" class Hello include A include B def s1 end end
main.rb
# !/usr/bin/ruby -w # -*- encoding:utf-8 -*- # filename: main.rb # author: 简单教程(www.twle.cn) # Copyright © 2015-2065 www.twle.cn. All rights reserved. require "hello" samp= Hello.new samp.a1 samp.a2 samp.b1 samp.b2 samp.s1
- 模块 A 由方法 a1 和 a2 组成
- 模块 B 由方法 b1 和 b2 组成
- 类 Hello 包含了模块 A 和 B
- 类 Hello 可以访问所有四个方法,即 a1、a2、b1 和 b2
可以看到类 Hello 继承了两个模块,可以说类 Hello 使用了多重继承或 mixin