Hi --
Navindra Umanee wrote:
Why does the first one work but not the second one?
As mathew said, def is just a command to define a method, it runs when the interpreter gets to that line. What makes the first one work and the second one not, however, is a matter of scope. When 'def' is called, it defines a method in a certain place. That place is determined by what 'class' or 'module' it's in. So class Test; def foo; end end defines a method on Test objects.
#1: def moo; puts 'moo' end is *not inside a 'class' or 'module' block*. This is important. You may be defining a class method boo on Test (well, a singleton method on the Test object), but your @@class_variables won't actually be class variables of Test, because it's outside the class block. It's out in the wild. Here's what the PickAxe2 (p. 346) has to say about that:
"Outside a class or module definition, a definition with an unadorned method name is added as a private method to class Object, and hence may be called in any context without an explicit receiver."
So what's happening here?
Test.boo calls the Test.boo method you defined, which defines a private method moo on Object. The 'def' keyword, as you've seen returns nil. So Test.boo returns nil. Test.boo.moo tries to invoke the moo method on the nil object. Since nil.is_a? Object, it has the moo method that you just defined.
(I'm thinking the PickAxe may be wrong? about the private thing since you can call #moo with an explicit receiver -- sounds more like public. Can somebody explain?)
I think the private thing depends on lexical scope. Since the nested
definition of moo is not lexically a top-level definition, it isn't
privatized.
#2: When Test.boo is called, moo is defined as an instance method on Test. Test.boo returns nil, as before, but nil is not a Test object, so the moo method does not exist.
What I find interesting is this:
class D
def D.boo
def moo
puts "moo"
end
end
def bee
def mee
puts "mee"
end
end
end
D.boo
d = D.new
d.bee
p D.instance_methods.sort # includes both moo and mee
Nesting a definition inside a class method, and nesting a definition
inside an instance method, have exactly the same effect: an instance
method is added to the class. In one case, this means "self"; in the
other, it means "self.class". I'm not sure why it works this way.
Maybe the real rule is "one lexical layer up", which would take both
to the class-definition scope that surrounds them.
David
···
On Sun, 11 Sep 2005, Devin Mullins wrote:
--
David A. Black
dblack@wobblini.net