Reputation: 355
In the following example:
Main.rb
def main
obj = ExampleClass.new
def multiply(a, b, c, d)
return a * b * c * d
end
puts obj.multiply(1, 2, 3, 4) # this prints 24
end
main
ExampleClass.rb
class ExampleClass
def initialize
end
end
Why is the multiply
method now part of the obj
instance? (the main
method is not part of the ExampleClass
definition)
Upvotes: 2
Views: 287
Reputation: 369428
Methods defined at script scope become private instance methods of Object
. (Except in IRb, where they become public instance methods of Object
.)
So, main
is a private instance method of Object
.
Method definitions inside methods do not create nested methods, i.e. multiply
is not nested in main
. Rather, each time you call main
, you will create a new method called multiply
as an instance method of Object
. And for some reason that is not quite clear to me, it ends up as a public method.
So, what happens is the following:
main
as a private instance method of Object
main
, which will in turn define multiply
as a public instance method of Object
multiply
, which works because obj
is an instance of ExampleClass
which is a subclass of Object
, which has your multiply
methodUpvotes: 2
Reputation: 2747
The code written without additional class .. end
, module .. end
enclosures is executed directly, step by step, in context of special main
object. This object can be referenced using:
2.2.2 :001 > self
# => main
Methods defined without additional classes/modules
are defined as private methods of the main
object, and, consequently, as private methods of almost any other object in Ruby:
2.2.2 :002 > def foo
2.2.2 :003?> 42
2.2.2 :004?> end
# => :foo
2.2.2 :005 > foo
# => 42
2.2.2 :006 > [].foo
# => NoMethodError: private method `foo' called for []:Array
2.2.2 :007 > [].send :foo
# => 42
Thus, in your code, main
method (or it can any other method) is in the context of main
object and so multiply
method can be called from either ExampleClass.new
or Array.new
or from any other class.
Source: Wikipedia
UPDATE
Few notes from engineersmnky's comment.
This is not a private method in main but rather a private method of BasicObject (in 2.0-2.2).
As of 2.3 (and in 1.9.3) this method is not even privatized.
It need not be an instance of the class
e.g. Class.new
as the class itself will also have this method defined e.g. BasicObject.foo
Upvotes: 3
Reputation: 401
Maybe it's because both the variable obj
and the context where the method multiply
was defined have Object
as parent/ancestor.
If you call obj.class
you will get ExampleClass < Object
. Supposing you are in the console, if you call self.class
, you will get Object < BasicObject
. So, in your code, you have defined a method multiply
for Object
class. That's why multiply
is part of obj
instance.
Upvotes: 2