Ruby 手册 | 10 - 模块介绍

169 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第10天,点击查看活动详情

一、模块介绍

在大型应用的编写过程中,保持良好的代码结构非常重要,模块就是一种将方法、类和常量组织在一起,形成一种层次结构的方式

模块的一大功能就是可以提供命名空间(namespace)的支持,在复杂应用中不可能将所有的代码都卸写在一个文件中,模块可以支持将不同的功能分解到不同的文件中,保持一种良好的层次结构,而且能被其他不同的程序引用,同时不同的模块可以有自己独立的命名空间,不同模块在不同的命名空间中可以有相同的方法名或者常量名而不受影响。Ruby 的基本库以及其他各种扩展库都是以模块的形式来组织的。

模块就像是一个容纳方法和常量的代码容器,里面是实现某些特定功能的代码吗,在需要的时候将各种模块拼接起来,形成一个新的模块,同时具备所包含的模块的所有功能。

这种方式类似工业化的生产组装,有些模块类似发动机的功能,有些类似轮子的功能,最后若干个模块组成一辆汽车,这种方式在 Ruby 中称作 Mixin。

模块的定义和类的定义是类似的,不过使用的是 module 关键字

module 模块名
    def 方法名
        ...
    end
end

模块在 Ruby 中也是对象,它是基于 Module 类,因此模块的许多特性和类相似

module YankeeMod

  def self.say_module_name
    puts "输出模块的名字为:YankeeMod"
  end
end

module YankeeMod
  NAME = "YankeeMod"

  module SubYankeeMod
    NAME = "SubYankeeMod"
  end
end

puts YankeeMod.class
YankeeMod.say_module_name

# 使用 :: 来引用模块中的模块或者方法
YankeeMod::say_module_name

puts YankeeMod::NAME
puts YankeeMod::SubYankeeMod::NAME

执行上述代码,输出结果如下:

Module
输出模块的名字为:YankeeMod
输出模块的名字为:YankeeMod
YankeeMod
SubYankeeMod

使用 :: 可以引用模块中的模块或者方法可以清晰的展示模块之间的层次关系,即使模块中有相同的方法或者变量也不会导致混淆。

Ruby 中的 Module 也是一个对象,所以 Module 是不可以实例化的,既 YankeeMod.new 是会报错的,模块中的普通方法可以在模块内部之间使用,另外模块被类包含引用的时候可以编程类的方法。

二、模块加载

在模块创建完成之后,下一步可能就是要在其他的地方引用这些模块,也就是加载或者混入模块。Ruby 中有 4 中方式可以实现这些功能,分别为 requireloadincludeextend

requireload 都是加载相应的模块到当前的环境中,load 比较直接,它会无条件的包含源文件,不管之前是否已经加载过,因此可以用来重新加载源代码,而 require 则会检查保证模块只被加载过一次。

require 常用与引用加载一些扩展库,要注意 require 和 load 加载后,被加载文件中的局部变量不会被加载进来。

load 'ex1.rb' # 加载 ex1.rb 文件
require 'yaml' # 加载 ymal 库,通常也是应用 yaml.rb 文件

如果传入的文件不包含路径,load 和 require 会自动在当前的目录中查找相关文件。

include 和 extend 不会自动加载文件,它们的作用只是将模块汇入或者扩展已有的类或者模块,include 实现的就是混入的功能,它会建立一个由类包含模块的引用,自动为类添加模块中所包含的方法,而且当模块放生改变的时候,类中混入的模块中的方法也会相应的改变。

extend 和 include 很类似,不过 extend 是用来在一个对象中引入一个模块,使得这个对象也具有这个模块的方法。

module XMod
  def say_hi
    puts "这是 M1 中的 say_hi 方法"
  end
end


# include 混入模块
class Xray
  include XMod
end

# extend 混入模块
class Whiskey
  extend XMod
end

# 实例化
x = Xray.new

# 类中使用 include 的模块的方法会变成实例方法,由实例对象引用
x.say_hi

# 类中使用 extend 的模块的方法会变成类方法,只能由类调用
Whiskey.say_hi

执行上述代码,输出结果如下:

这是 M1 中的 say_hi 方法
这是 M1 中的 say_hi 方法

使用 include 引入模块相当于在类中定义实例方法,而 extend 引入相当于在类中定义类方法。

class Xray
    def say_hi
        puts "这是 M1 中的 say_hi 方法"
    end
end

class Whiskey
    def self.say_hi
        puts "这是 M1 中的 say_hi 方法"
    end
end

三、内置类和标准库

Ruby 解释器中包含了 30 多个内置类,本质上来说这些内置类以及方法构成了 Ruby 的世界。如果能够对这些 Ruby 内置类有所了解,对于编写 Ruby 代码也是非常有帮助的。

前面应了解 Ruby 内置类中的 Class 类和 Module 类,它们都继承值 BasicObject 类。Ruby 中连对象的方法都是一种对象,基于 Method 类。

Ruby 中的数据类型都继承自 Numeric 类

图片.png

除了数字类型之外,还包括 IO 相关类,异常相关类和进程相关类。

除了内置类之外,Ruby 还有一个庞大的标准库,提供的功能覆盖了包括系统处理、网络、数据加密等应用方面,而且都是各个领域比较标准的解决方法,在使用时字需要通过 require 关键字加载响应的模块即可,并且安装 Ruby 时也会安装整个标准库,如果需要的库在标准库中也可以通过 gem 工具来查找和安装。