Ruby 简明教程

Ruby - Modules and Mixins

模块是将方法、类和常量分组在一起的一种方式。模块给您带来了两大好处:

  1. 模块提供了一个名称空间并防止名称冲突。

  2. 模块实现 Mixin 机制。

模块定义了一个名称空间,一个沙盒,您可以在其中使用您的方法和常量,而不用担心被其他方法和常量踩到。

Syntax

module Identifier
   statement1
   statement2
   ...........
end

模块常量的命名方式与类常量相同,以大写字母开头。方法定义看起来也很相似:模块方法的定义方式与类方法相同。

与类方法一样,您可以通过在方法名称前面加上模块名称和一个句点来调用模块方法,并且可以使用模块名称和两个冒号来引用常量。

Example

#!/usr/bin/ruby

# Module defined in trig.rb file

module Trig
   PI = 3.141592654
   def Trig.sin(x)
   # ..
   end
   def Trig.cos(x)
   # ..
   end
end

我们可以使用相同的函数名称但不同的功能来定义另一个模块:

#!/usr/bin/ruby

# Module defined in moral.rb file

module Moral
   VERY_BAD = 0
   BAD = 1
   def Moral.sin(badness)
   # ...
   end
end

与类方法一样,在模块中定义方法时,您需要指定模块名称,后跟一个点,然后再指定方法名称。

Ruby require Statement

require 语句类似于 C 和 C++ 的 include 语句,以及 Java 的 import 语句。如果第三方程序想要使用任何已定义的模块,它只需使用 Ruby require 语句加载模块文件即可:

Syntax

require filename

这里,不需要给文件名称加上 .rb 扩展名。

Example

$LOAD_PATH << '.'

require 'trig.rb'
require 'moral'

y = Trig.sin(Trig::PI/4)
wrongdoing = Moral.sin(Moral::VERY_BAD)

在这里,我们使用 $LOAD_PATH << '.' 使 Ruby 了解到包含的文件必须在当前目录中搜索。如果您不想使用 $LOAD_PATH,则可以使用 require_relative 从相对目录包含文件。

IMPORTANT - 在此,两个文件都包含相同的函数名称。因此,这将在包含到调用程序时导致代码歧义,但模块避免了这种代码歧义,我们能够使用模块名称调用适当的函数。

Ruby include Statement

您可以将模块嵌入到类中。要将模块嵌入到类中,您可以在类中使用 include 语句:

Syntax

include modulename

如果模块在一个单独的文件中定义,那么在将模块嵌入到类中之前需要使用 require 语句包含该文件。

Example

考虑 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

这会产生以下结果 −

Sunday
You have four weeks in a month
You have 52 weeks in a year
Sunday
120

Mixins in Ruby

在通读本节之前,我们假定您了解面向对象的概念。

当一个类可以从多个父类中继承特征时,该类应当展示多重继承。

Ruby 不直接支持多重继承,但 Ruby 模块还有另一个美妙之处。总的来说,它们极大地消除了对多重继承的需求,提供了被称为混合的功能。

混合为您提供了一种受控良好的方式来对类添加功能。但是,当混合中的代码开始与使用它的类中的代码进行交互时,它们的真正威力才会显现出来。

让我们研究以下示例代码来了解混合 −

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

模块 A 包含方法 a1 和 a2。模块 B 包含方法 b1 和 b2。类 Sample 包含模块 A 和 B。类 Sample 可以访问所有四个方法,即 a1、a2、b1 和 b2。因此,您可以看到,类 Sample 从两个模块均继承。因此,您可以说类 Sample 展示了多重继承或混合。