模块中的实例方法

请考虑以下代码:

module ModName def aux puts 'aux' end end 

如果我们用class替换module ,我们可以执行以下操作:

 ModName.new.aux 

但是,模块不能被实例化。 有没有办法在模块上调用aux方法?

想想什么是aux 。 什么对象会响应aux ? 它是一个实例方法,这意味着包含ModName的类的实例将响应它。 ModName模块本身不是此类的实例。 如果您已将ModName定义为类,则此操作也无效 – 您无法在没有实例的情况下调用实例方法。

模块非常类似于可以混合到其他类中以添加行为的类。 当一个类混合在一个模块中时,所有模块的实例方法都成为该类的实例方法。 这是实现多重inheritance的一种方式。

它们还充当命名空间的替代品,因为每个模块都定义了命名空间。 但这有点无关。 (顺便说一句,类也有自己的命名空间,但是使它成为一个类意味着你将创建它的实例,因此它们在概念上是错误的。)

你可以这样做:

 module ModName def aux puts 'aux' end module_function :aux end 

然后只需调用它:

 ModName.aux 

你也可以说

 module ModName extend self def aux puts 'aux' end end 

然后你可以正常包含模块,也可以通过ModName调用方法。

模块定义评估为“这是……”,为什么?

在Ruby中,一切都是表达式,没有语句或声明。 这意味着每次迭代都会计算出一个值。 (但是,这并不一定意味着它计算为有用的值。例如, puts方法总是求值为nil ,就像def方法定义表达式一样(Rubinius除外,其中def表达式求值为CompiledMethod对象正在定义的方法)。)

那么,如果一切都评估为一个值,模块定义表达式应该评估什么? 好吧,有几个候选者:它可以评估为nil ,就像方法定义表达式一样。 或者它可以评估模块对象本身,毕竟,这我们正在定义的,对吧? 但实际上,Matz选择了第三种选择:模块(和类)定义表达式实际上评估模块定义体内的最后一个表达式求值。 (这使您可以通过将nilself作为模块定义主体中的最后一个表达式来轻松模拟其他两种可能性。)

在您的情况下,模块定义主体内的最后一个表达式是赋值。 但是,作业? 回归到底是什么? 这不是一个声明吗? 不,不是在Ruby中。 一切都是表达式,并且赋值也不例外:赋值表达式求值为右侧评估的任何值。 这里,赋值表达式的右侧是一个字符串文字,它的计算结果为字符串对象。

因此,整个模块定义表达式求值为字符串'this is a const in module'

还有一点……

 module Y def Ya puts "a" end def Yb c end def self.c puts "b -- c" end end 

打电话(没有’.new’):

 Ya #=> "a" Yb #=> "b -- c" Yc #=> "b -- c" 
 class Foo include ModName end Foo.new.aux # output: aux