Post

Ruby的module

模块module

module最主要的功能是起命名空间的作用,可以把数据和方法集合在一起用来进行引用,直接上代码测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module Mod_a
  PI = 3.14
  def self.num(a)
    a
  end
end

x = Mod_a::PI
y = Mod_a::num(3)
z = Mod_a.num(4)
puts x
puts y
puts z


3.14
3
4

可以看到,moduleclass很类似,可以定义方法,常量,也可以在程序中直接引用,但是要注意,module是不能实例化的,所以只能以类的方式去引用方法,所以这里定义的是self.num的方法,如果定义的是num方法,则不能直接使用,必须要导入module来使用

include

1
2
3
4
5
6
7
8
9
##module.rb

module Mod_a
  PI = 3.14
  def num(a)
    a
  end
end

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require "./module"

class Book
  include Mod_a
end

book = Book.new
x = book.num(5)

puts Book::PI
puts x

3.14
5

可以看到,通过导入module.rb,include Mod_a,就可以直接用module里的方法以及数据了,可以被类加载成实例方法,这种操作叫做mixin,和类的继承不同,mixin更灵活,可以让不同的类加载不同的module

extend

通过include的方式,module里的方法会成为include类的实例方法(注意是直接定义方法名不是def self.method的形式 ),如果想变成类方法就要用extend方式了

1
2
3
4
5
6
7
8
9
require "./module"

class Book
  extend Mod_a
end

puts Book.num(5)

5

可以看到此时是以类方法的形式去引用module里的方法,而不能实例化去引用

include和extend的差异

可以出include可以简单的理解为把module里的代码全部复制进去,但是extend会做一些改变,让方法才能以类方法的形式使用,所以如果include的方式实现类方法就很好理解了,就是在module定以方法的时候用def self.method方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
##module.rb

module Mod_a
  def self.num(a)
    a
  end
end
----------------
class Book
  include Mod_a
end

puts Book.num(5)

5

因为include就相当于把代码复制进来,所以self.num就相当于类定义的类方法

思考

1
2
3
4
5
6
7
8
##module.rb

module Mod_a
  PI = 3.14
  def num(a)
    a
  end
end
1
2
3
4
5
6
7
8
9
require "./module"

class Book
  extend Mod_a
end

puts Book::PI

mod_a.rb:12:in `<main>': uninitialized constant Book::PI (NameError)

引用module中的常量前面已经验证过,include方式是正常的,但是用extend的方式就会报错了,具体原因还没去查证,总之明白结论就好了。另外module还可以嵌套moduleclass,但是其本质都是一样,本质都可以认为是起一个命名空间的作用。

include方式相当于把代码复制过去,变成mixin类的等同实例方法或者类方法,extend是类的实例方法去mixin,如果有常量的话,一定要用include方式

This post is licensed under CC BY 4.0 by the author.