深入 Ruby 中的 Module

模块不能被实例化,也不能被子类化,模块是独立的,且一个模块对像是Module类的一个实例。模块最常用的两个用途是作为命空间和混入(mixin)。

在模块中,可以定义实例变量、实例方法、类变量、类方法和属性等,并且在模块中还可能以定义类和模块。在类中也可以定义模块。

在访问模块中的实例成员,需要在类中饱含模块,然后实例化类以访问模块的实例成员。

1
2
3
4
5
6
7
module Foo
PI = 3.14
def caculate
PI
end
end

命名空间

可以将Class定义在module下,这样就避免命名冲突。module和目录没有关系,这和有些语言不大相同。

1
2
3
4
module Peoject
class User
end
end

多层结构

1
2
3
4
module A
module B
end
end

也可以写成这种A::B格式,前提是A已经提前声明过,不然会出错。REF

1
2
module A::B
end

有时候也可以这样::B,这声明的是

1
2
module ::B
end

Mixin

Ruby只支持单继承,而又不像C#一样可以实现多个接口,对于多类共用的一些定义,提供了mixin的方法,就是把module中的变量、方法全部加入到当前类中。

有2种方法来实现加入:

  • include
    该方法主要用来将一个模块插入(混入)到一个类或者其它模块。在类定义中引入模块,使模块中的方法成为类的实例方法;这个模块的方法在引入它的类或模块中以函数的形式调用,include 并非将模块的实例方法简单 拷贝到类中, 而是建立了一个类到模块的引用。,如;

    在使用include来加载一个module之前,要先require这个module对应的文件。Rails中使用了一种自动加载的机制,会主动来加载相应目录下的文件,但Rails外,都要手动来require。

  • extend
    extend 用来在一个对象(object,或者说是instance)中引入一个模块,这类从而也具备了这个模块的方法,如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module FirstModule
def helloMod
puts "This is a module."
end
end
class FirstClass
def helloClass
puts "This is a class."
end
end
c=FirstClass.new
c.helloClass #This is a class.
c.extend(FirstModule)
c.helloMod #This is a module.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module Highlander
module Abc
module Guarda
def abcd
p 'abcd'
end
end
end
end
module Highlander
class API
include Abc::Guarda
def hello
p 'hello'
end
end
end
samp = Highlander::API.new
samp.hello
samp.abcd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
module Highlander
end
module Highlander::Abc
module Guarda
def abcd
p 'abcd'
end
end
end
module Highlander
class API
include Abc::Guarda
def hello
p 'hello'
end
end
end
samp = Highlander::API.new
samp.hello
samp.abcd

类方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
同名方法。
self方法
目录和模块的关系。
ModuleName.function_name
self.function_name
module继承于Object
所以module_name和self.function_name是类方法
Module 中方法定义
普通的则是实例方法。
通过ModuleName.function_name 调用 。
http://stackoverflow.com/questions/963378/ruby-rails-context-of-self-in-modules-and-libraries
Module中Class定义

????

1
2
3
4
5
6
7
8
9
10
11
12
module B
class << self
include A
end
end
B.method
module B
extend A
end

REF::

ii. require 和 load的区别:

load方法参数要求是包括文件扩展名的完整文件名,require则只需要传入库的名字,不需要像文件名那样的后缀;
load把一个文件加载多次,而require则最多只能加载一次;
require方法不公可以加载ruby源文件,还可以加载其它语言编写的源文件;load方法的作用就是复制和粘贴;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
module A
def a1
p 'a1'
end
def a2
p 'a2'
end
module C
def c1
p 'c1'
end
end
end
module B
def b1
p 'b1'
end
def b2
p 'b2'
end
end
class Sample
include A
include B
include C
def s1
p 's1'
end
end
samp=Sample.new
samp.a1
samp.a2
samp.b1
samp.b2
samp.c1
samp.s1
如果不include c ,则无法调用C1
module A::C
def c1
end
end