Reputation: 1344
I'm trying to understand why I can't call methods defined on the singleton class from within the open class but I can from the actual class.
Can someone explain why the first example fails and the second one doesn't?
class One
class << self
def one; end
one
end
end
NameError (undefined local variable or method 'one' for #<Class:One>)
class Two
class << self
def one; end
end
self.one
end
=> nil
Upvotes: 4
Views: 54
Reputation: 369438
Your example is more confusing than it needs to be. It doesn't require a singleton class at all:
class Foo
def bar; end
bar # NameError
end
Foo.new.bar
Here, we have a class Foo
with an instance method bar
. A singleton class is still just a class, so this is actually the exact same example as yours.
def
without an explicit definee defines an instance method of the closest lexically enclosing class definition, in this case Foo
. A message send without an explicit receiver like bar
sends the message to self
. Inside the class definition body, self
is the class itself.
So, def bar
defines an instance method in Foo
, i.e. a method you can call on instances of Foo
.
bar
inside the class definition body sends a message to self
, which is Foo
. Since Foo
is not an instance of itself, it does not have a method named bar
, ergo, the method call fails.
This works exactly the same with a singleton class, since it is still just a class.
Upvotes: 2
Reputation: 121000
You made the wrong assumption about where the method belongs to, in the first place. The call to the instance method one
from inside class context should not succeed. In your first snippet, you try to call method one
from the singleton class of the singleton class of One
(because it’s called from singleton_class
context).
Example with normal class / instance methods to clarify:
class One
def self.one()
puts :class
end
def one
puts :instance
end
one()
end
#⇒ class
So, the expected behavior would be to raise NameError
. Now the answer is simple: it raises NameError
because this method does not exist.
Upvotes: 0