flyingL123
flyingL123

Reputation: 8086

def vs. define_method in Ruby

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

Answers (2)

Dmitry Sokurenko
Dmitry Sokurenko

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

7stud
7stud

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

Related Questions