简体   繁体   English

模块中的实例方法

[英]Instance methods in modules

Consider the following code: 请考虑以下代码:

module ModName
  def aux
    puts 'aux'
  end
end

If we replace module with class , we can do the following: 如果我们用class替换module ,我们可以执行以下操作:

ModName.new.aux

Modules cannot be instanced, though. 但是,模块不能被实例化。 Is there a way to call the aux method on the module? 有没有办法在模块上调用aux方法?

Think about what aux is. 考虑一下aux是什么。 What object will respond to aux ? 什么对象会响应aux It's an instance method, which means that instances of classes that include ModName will respond to it. 它是一个实例方法,这意味着包含ModName的类的实例将响应它。 The ModName module itself is not an instance of such a class. ModName模块本身不是此类的实例。 This would also not work if you had defined ModName as a class — you can't call an instance method without an instance. 如果您已将ModName定义为类,则此操作也无效 - 您无法在没有实例的情况下调用实例方法。

Modules are very much like classes that can be mixed into other classes to add behavior. 模块非常类似于可以混合到其他类中以添加行为的类。 When a class mixes in a module, all of the module's instance methods become instance methods of the class. 当一个类混合在一个模块中时,所有模块的实例方法都成为该类的实例方法。 It's a way of implementing multiple inheritance. 这是实现多重继承的一种方式。

They also serve as substitutes for namespaces, since each module defines a namespace. 它们还充当命名空间的替代品,因为每个模块都定义了命名空间。 But that's somewhat unrelated. 但那有些不相干。 (Incidentally, classes also have their own namespaces, but making it a class implies that you'll create instances of it, so they're conceptually wrong for that purpose.) (顺便说一句,类也有自己的命名空间,但是使它成为一个类意味着你将创建它的实例,因此它们在概念上是错误的。)

You can do it this way: 你可以这样做:

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

and then just call it: 然后只需调用它:

ModName.aux

You can also say 你也可以说

module ModName
  extend self

  def aux
    puts 'aux'
  end
end

Then you can include the module normally, but also call methods via ModName. 然后你可以正常包含模块,也可以通过ModName调用方法。

the module definition evaluates to 'this is...', why? 模块定义评估为“这是......”,为什么?

In Ruby, everything is an expression, there are no statements or declarations. 在Ruby中,一切都是表达式,没有语句或声明。 Which means that everyhing evaluates to a value. 这意味着每次迭代都会计算出一个值。 (However, this doesn't necessarily mean that it evaluates to a useful value. For example, the puts method always evaluates to nil , just like a def method definition expression (except in Rubinius, where the def expression evaluates to a CompiledMethod object for the method being defined).) (但是,这并不一定意味着它会计算为有用的值。例如, puts方法总是求值为nil ,就像def方法定义表达式一样(Rubinius除外,其中def表达式求值为CompiledMethod对象正在定义的方法)。)

So, if everything evaluates to a value, what should a module definition expression evaluate to? 因此,如果所有内容都计算为值,那么模块定义表达式应该评估什么? Well, there are a couple of candidates: it could evaluate to nil , just like a method definition expression. 好吧,有几个候选者:它可以评估为nil ,就像方法定义表达式一样。 Or it could evaluate to the module object itself, after all, this is what we are defining, right? 或者它可以评估模块对象本身,毕竟,这我们正在定义的,对吧? But actually, Matz chose a third option: module (and class) definition expressions actually evaluate to whatever the last expression inside the module definition body evaluates to. 但实际上,Matz选择了第三种选择:模块(和类)定义表达式实际上评估模块定义体内的最后一个表达式求值。 (This allows you to easily simulate the other two possibilities by just putting nil or self as the last expression inside a module definition body.) (这使您可以通过将nilself作为模块定义主体中的最后一个表达式来轻松模拟其他两种可能性。)

In your case, the last expression inside the module definition body is an assignment. 在您的情况下,模块定义主体内的最后一个表达式是赋值。 But, an assignment? 但是,作业? What the heck does that return? 回归到底是什么? Isn't that a statement? 这不是一个声明吗? No, not in Ruby. 不,不是Ruby。 Everything is an expression, and assignments are no exception: assignment expressions evaluate to whatever the right hand side evaluates to. 一切都是表达式,赋值也不例外:赋值表达式求值为右侧评估的任何值。 Here, the right hand side of the assignment expression is a string literal, which evaluates to a string object. 这里,赋值表达式的右侧是一个字符串文字,它的计算结果为字符串对象。

So, the entire module definition expression evaluates to the string 'this is a const in module' . 因此,整个模块定义表达式求值为字符串'this is a const in module'

And a little more... 还有一点......

module Y
  def Y.a
    puts "a"
  end

  def Y.b
    c
  end

  def self.c
    puts "b -- c"
  end
end

call (without '.new'): 打电话(没有'.new'):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM