Reputation: 8086
I'm experimenting with Ruby and am confused by the following behavior. In a file test.rb
I have the following code:
def my_method
puts "Output of my_method"
end
define_method(:my_other_method) do
puts "Output of my_other_method"
end
puts methods
I run this file from the command line using ruby test.rb
, and the output is a list of methods:
to_s
inspect
my_other_method
nil?
===
=~
!~
eql?
hash
<=>
class
singleton_class
clone
dup
itself
taint
tainted?
untaint
untrust
untrusted?
trust
freeze
frozen?
methods
singleton_methods
protected_methods
private_methods
public_methods
instance_variables
instance_variable_get
instance_variable_set
instance_variable_defined?
remove_instance_variable
instance_of?
kind_of?
is_a?
tap
send
public_send
respond_to?
extend
display
method
public_method
singleton_method
define_singleton_method
object_id
to_enum
enum_for
==
equal?
!
!=
instance_eval
instance_exec
__send__
__id__
As you can see, my_other_method
is in the list, but my_method
is not. What causes this?
Upvotes: 0
Views: 596
Reputation: 6132
Calling def
on the top level declares a method as a private method of the Object
class, thus you don't see it in the list of public methods. But you still can call it directly anywhere on the top level and from inside of an object of any class.
Example:
def my_method
puts "Output of my_method"
end
class Foo
def use_my_method
my_method # it can be called there
end
end
Foo.new.use_my_method
my_method
Upvotes: 1
Reputation: 48599
As you can see, my_other_method is in the list, but my_method is not. What causes this?
Ruby treats defs
at the toplevel differently than defs
inside a class: toplevel defs become private methods of the Object class. Yet:
Object#methods: Returns a list of the names of public and protected methods...
def my_method
puts "Output of my_method"
end
define_method(:my_other_method) do
puts "Output of my_other_method"
end
print "public and protected:\n\t"
puts methods.grep(/my/)
print "private:\n\t"
puts private_methods.grep(/my/)
--output:--
public and protected:
my_other_method
private:
my_method
It's undocumented, but define_method()
actually creates a public
method:
print "public:\n\t"
puts public_methods.grep(/my/)
--output:--
public:
my_other_method
And:
p Object.public_methods.grep(/my/)
--output:--
[:my_other_method]
Upvotes: 1