meizin
meizin

Reputation: 221

Calling instance method in Class in Ruby

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

Answers (4)

David Hoelzer
David Hoelzer

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

Cary Swoveland
Cary Swoveland

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

J&#246;rg W Mittag
J&#246;rg W Mittag

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

steenslag
steenslag

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

Related Questions