Reputation: 221
I am very confused about this. In Programming Ruby book, it says, "receiver checks for the method definition in its own class"
So class object stores all instance methods. Then why can't I call instance method from within a class?
For example:
class ExampleClass
def example_method
end
example_method
end
I cannot call example_method inside ExampleClass.
However, if I define a method in top level like this:
class ExampleClass
def example_method
end
end
def example_method1
end
example_method1
Then I can call top level method example_method1.
Isn't top level also a class? How come it is different than a calling instance method from within ExampleClass?
Upvotes: 4
Views: 8142
Reputation: 16331
The biggest reason that you cannot call that function in the way that you have written it is that it is, as you say, an instance method.
Try defining it in this way:
class ExampleClass
def self.class_method
puts "I'm a class method"
end
class_method
end
I believe you will find that you have a different result. It's not that it's "Top Level", it's whether or not it's in scope for what you're dealing with. Since you're dealing with a class, a class method would be necessary. If you're dealing with an object (an instantiated class) it's a different "scope".
Upvotes: 5
Reputation: 110675
I'll try to explain it as follows.
class MyClass
def self.my_method
puts "Me, I'm a class method. Note that self = #{self}"
end
def my_method
puts "Me, I'm an instance method. Note that self = #{self}"
end
# I'm about to invoke :my_method on self. Which one will it be?"
# "That depends on what self is now, of course.
puts "self = #{self}"
# OK. It's MyClass. But wait. I'm just defining the set now.
# Do the methods I defined above even exist yet?
# Does the class exist yet? Let's find out.
print "class methods: "
puts self.methods(false)
print "instance methods: "
puts self.instance_methods(false)
# Cool! Let's try invoking my_method
my_method
# It worked. It was the class method because self = MyClass
# Now let's see if we can create an instance of the class before
# we finish defining the class. Surely we can't.
my_instance = new
puts "my_instance = #{my_instance}"
# We can! Now that's very interesting. Can we invoke the
# instance method on that instance?
my_instance.my_method
# Yes!
end
The following is printed while the class is being defined:
self = MyClass
class methods: my_method
instance methods: my_method
Me, I'm a class method. Note that self = MyClass
my_instance = #<MyClass:0x007fd6119125a0>
Me, I'm an instance method. Note that self = #<MyClass:0x007fd6119125a0>
Now let's confirm the methods can be invoked from outside the class. There should be no surprises here:
MyClass.my_method
#-> Me, I'm a class method. Note that self = MyClass
my_instance = MyClass.new
my_instance.my_method
#-> Me, I'm an instance method. Note that self = #<MyClass:0x007fd61181d668>
Upvotes: 2
Reputation: 369458
The receiver checks for the method definition in its own class. The receiver is ExampleClass
. The class of ExampleClass
is Class
. There is no example_method
method in the Class
class, ergo, you get a NoMethodError
.
Upvotes: 2
Reputation: 80065
Those "global" methods are an exception. They are defined as private instance methods of Object. Everything inherits from Object, so these methods are "globally" visible.
p self.class # => Object
p self.private_methods.sort # => [:Array, :Complex, ... :using, :warn] # all (?) from Kernel module
def aaaa
end
p self.private_methods.sort # => [:aaaa, :Array, ... :using, :warn]
Upvotes: 3