第六章 模块和程序组织
一、创建和使用模块的基础知识
1. 除了使用 module 关键字来替代 class 关键字之外,编写模块和编写类很相似
module MyFirstModule
end
2. 使用模块
class ModuleTester
end
mt = ModuleTester.new
mt.say_hello
二、封装似栈特性的模块
1. 封装具有似栈性的结构和行为的 Stacklike 模块(保存到 stacklike.rb 文件中)
module Stacklike
end
2. 将 Stacklike 模块混含到 Stack 类中,使用 Stack 类的实例
require "stacklike"
class Stack
end
s = Stack.new
s.add_to_stack("item one")
s.add_to_stack("item two")
s.add_to_stack("item three")
puts "Objects currently on the stack:"
puts s.stack
taken = s.take_from_stack
puts "Removed this object:"
puts taken
puts "Now on stack:"
puts s.stack
运行结果
Objects currently on the stack:
item one
item two
item three
Removed this object:
item three
Now on stack:
item one
item two
三、模块、类和方法查找
1. 从对象角度看方法查找
module M
end
class C
end
class D < C
end
obj = D.new
obj.report
类 D 的对象实例的方法查找过程图
2. 一条方法查找路径上的两个同名方法
module M
end
class C
include M
end
c = C.new
c.report # 输出:'report' method in class C
3. 混含定义了同名方法的两个模块
module M
end
module N
end
class C
end
c = C.new
c.report # 输出:'report' method in module N
4. 用 super 提升方法查找路径
module M
end
class C
end
c = C.new
c.report
输出结果
'report' method in class C
About to trigger the next higher-up report method...
'report' method in module M
Back from the 'super' call.
四、类/模块的设计和命名
1. 使用类还是模块?
(1)模块没有实例。因此实体或事物最好建模为类,而实体或事物的特性最好建模为模块,因此我们倾向于使用名词作为类名,使用形容词作为模块名。
(2)一个类中有一个父类,但它可以混含任意多个模块。如果使用继承,要慎重考虑生成一个合理的父类/子类关系。如果使用一个类唯一的父类关系最后却发现几组特性中只有一个赋予了该类,那么这个关系还是不要用的好。
2. 嵌套的模块和类
模块和类可以相互嵌套
module Tools
class Hammer
要产生定义在 Tools 模块中的 Hammer 类的实例,须用双冒号(::)访问该类
h = Tools::Hammer.new
3. Rails 源代码中样版代码中的模块组织
class Composer < ActiveRecord::Base
end