模块
Ruby中的类是表现事物的属性和行为,那么模块呢?,在Ruby中模块表现的只是事物的行为。
模块与类的区别于下:
- 模块不能拥有实例
- 模块不能被继承
如何访问模块内的方法?有两种方式可以访问
1.使用模块名.方法名的形式来直接调用模块中定义的方法。
1 | Math.sqrt(4) #=> 2.0 |
2.通过include 模块名的形式预先将模块引入到当前的命名空间,然后就可直接访问模块内的方法和常量。
1 | include Math |
第二种方式也就是Mix-in扩展类的功能,将模块混合到类中。在定义类时使用include引入指定的模块后,此时该类就可以使用模块里的所有方法和常量,从而增加了该类的功能。
Mix-in可以灵活地解决以下问题:
- 虽然两个类拥有相似的功能,但是不希望把他们作为相同的种类(Class)来考虑的时候,此时可将相似功能封装为模块供这两个类使用
- Ruby不支持父类的多重继承,因此无法对已经继承的类添加共同的功能的时候
1 | class Calculator |
创建模块
使用module关键来创建模块,模块名的首字母必须大写
module 模块名
模块定义
end
1 | module HelloModule |
在上面代码中,我们可以看到module_function方法,此方法主要用于将需要把模块函数公开给外部使用,其参数是表示方法方法名的符号,可以跟多个参数。
注:不建议在定义为模块函数的方法中使用self
Mix-in
前面提到的,在类中使用include引入模块,此时类的功能将得到增强。
如果想知道类是否包含某个模块,可以使用include?方法,如之前的Calculator类中。
1 | Calculator.include?(Math) #=> true |
Ruby中类的实例在调用方法时的顺序为,该类>包含的模块>该类的父类等这个顺序查找该方法。
1 | module HelloModule |
以上代码中调用的是module中的方法。
用ancestors方法和superclass方法调查类的继承关系。superclass方法可直接返回类的父类
1 | p HelloClass.ancestors #=> [HelloClass, HelloModule, Object, Kernel, BasicObject] |
Kenerl是Ruby内部的一个核心模块,Ruby程序运行时所需的共通函数都封装在此模块中。
单一继承的优点就是简单,不会因为过多的继承而导致类之间的关系变得复杂。所以我们需要灵活使用单一继承和Mix-in。
Mix-in查找方法的规则
- 优先使用原来中定义的同名方法。
- 在同一个类中包含多个模块时,优先使用最后一个包含的模块。
- 嵌套include时,查找顺序也是线性的。
- 相同的模块被包含两次也上的,第2次以后的会被省略。
Object#extend方法
利用Object#extend方法可以使单例类包含模块,并把模块的功能扩展到对象中。
1 | module Welcome |
include可以帮助我们突破继承的限制,通过模块扩展类的功能;而extend则可以帮助我们跨过类,直接通过模块扩展对象的功能.
所有类本身都是Class类的对象,类方法就是类对象的实例方法。可以把类方法理解为下:
- Class类的实例方法
- 类对象的单例方法
使用extend方法为类对象追加类方法,使用include方法追加实例方法。
1 | module ClassMethod |