开发者

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:

ModName.new.aux

Modules cannot be instanced, though. Is there a way to call the aux method on the module?


Think about what aux is. What object will respond to aux? It's an instance method, which means that instances of classes that include ModName will respond to it. The ModName module itself is not an instance of such a class. This would also not work if you had defined ModName as a class — you can't call an instance method without an instance.

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.


the module definition evaluates to 'this is...', why?

In Ruby, everything is an expression, there are no statements or declarations. 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).)

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. 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. (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.)

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. 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'.


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'):

Y.a #=> "a"
Y.b #=> "b -- c"
Y.c #=> "b -- c"


class Foo
  include ModName
end
Foo.new.aux
# output: aux
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜