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
精彩评论