Ruby 中引入 Module(模块),是为了提供单继承和多继承机制。 模块用关键字 module 定义,与定义类的 class 类似。 模块中的方法等的定义和类一样。 但模块不能被实例化,也不能从普通类继承。 模块是独立的,且一个模块对像是 Module 类的一个实例。 在类中可以通过 include 继承模块中的方法,因为是继承而不是复制,所以,当类中有相同命名的方法时,优先执行类中的方法。 模块最常用的两个用途是:命名空间(Namespace)和混入(Mix-in)。 前者解决了命名冲突,后者解决了代码的复用。 下面,主要用实例,介绍一下使用模块时的,include 和 extend 方法的区别。
该方法主要用来将一个模块包含到(混入)一个类或者其它模块。 在类定义中引入模块,使模块中的方法成为类的实例方法。 include 后的模块,出现在类的父类查找链上,实例方法调用时,若在本类中找不到方法。 将会沿着继承树,向上从模块中检索。
module Human def eat puts "eat" end end class Boy include Human end Boy.ancestors => [Boy, Human, Object, Kernel, BasicObject] Boy.singleton_class.ancestors => [Class, Module, Object, Kernel, BasicObject] Boy.new.eat => eat
在类定义中引入模块,使模块中的方法成为类的类方法。 extend 后的模块,出现在了类的单例父类的链上,类方法调用时,将会依次从链上检索。
class Girl extend Human # Same as the following line # Girl.singleton_class.send :include, Human end Girl.ancestors => [Girl, Object, Kernel, BasicObject] Girl.singleton_class.ancestors => [Human, Class, Module, Object, Kernel, BasicObject] Girl.eat => eat
module Human def self.included(base) base.extend(ClassMethods) end def eat puts "eat" end module ClassMethods def sleep puts "We don't sleep." end end end class Programmer include Human end Programmer.new.eat => eat Programmer.sleep => We don't sleep. Programmer.ancestors => [Programmer, Human, Object, Kernel, BasicObject] Programmer.singleton_class.ancestors => [Human::ClassMethods, Class, Module, Object, Kernel, BasicObject]
参考链接
Include vs Extend in Ruby
Ruby学习笔记-Module
2015-07-25