Reputation: 18804
Consider the following code:
class Emotion
def confused?
def confused?
'yes'
end
'no'
end
end
am_i = Emotion.new
am_i.confused? # => "no"
am_i.confused? # => "yes"
5.times.map { Emotion.new.confused? } # => ["yes", "yes", "yes", "yes", "yes"]
Explanation:
confused?
the first time returns "no"
and re-defines itself.confused?
the second time invokes the new method that returns "yes"
.Though the above functionality is clear, I am not sure how both methods are being defined to the same scope.
The reason I ask is because:
@variable
inside and outside a method it has different meanings.self
. Won't the inside definition of the confused?
method have a different scope in comparison with the outside definition?def
actually determine where to define the method?Upvotes: 2
Views: 403
Reputation: 15171
A variable cannot be accessed in similar fashion inside and outside a method; for instance: if I define @variable inside and outside a method it has different meanings.
When setting instance variables with @x = y
syntax, the instance variables are set for self
.
I have learned that method definition changes self. Won't the inside definition of the confused? method have a different scope in comparison with the outside definition?
The scope can change, but in this case it doesn't. The value of self
inside a method is always the object that the method is being called on. In both of your confused?
method definitions, self
is an instance of Emotion
.
How does def actually determine where to define the method?
The answer to this (at least in MRI) is actually somewhat unintuitive. Every scope has a reference to a "default definee" object which is not necessarily related to self
and is always an instance of Module
. def
in that scope will define a method for the default definee. The most trivial way to get the default definee in ruby code is this:
eval("def __m; end; m = method(:__m); undef __m; m.owner")
For example, running that at the top level of a ruby program returns Object
. So, the default definee for the toplevel scope is Object
.
Here is some code which can hopefully answer your questions about scopes:
# `self` is the toplevel object
# default definee is `Object`
class X
# `self` is X
# default definee is also X
@a = 1 # defines instance variable @a for `X`
def y # defines method 'y' on X
# `self` is an instance of X
# default definee is X
@b = 2 # defines instance variable @b for an instance of `X`
def z # defines method 'z' on X
# `self` is still an instance of X
# default definee is still X
@c = 3 # defines instance variable @c for an instance of `X`
end
end
class << self
# `self` is the metaclass of X
# default definee is also the metaclass of X
@d = 4 # defines instance variable @d for the metaclass of X
end
end
It is important to remember that methods are always stored in instances of Module
, where as instance variables can be stored in any object (excluding primitives like nil
or booleans or integers).
Upvotes: 3