8

I read this:

Let’s start with a simple Ruby program. We’ll write a method that returns a cheery, personalized greeting.

def say_goodnight(name)
    result = "Goodnight, " + name
    return result
end

My understanding is that a method is a function or subroutine that is defined in a class, which can be associated to a class (class method) or to an object (instance method).

Then, how can that be a method if it was not defined within a class?

user2864740
  • 60,010
  • 15
  • 145
  • 220
Patricio Sard
  • 2,092
  • 3
  • 22
  • 52
  • 3
    Recall that methods return the last value calculated. For that reason, this method would normally be written `def say_goodnight(name); "Goodnight, " + name; end`. Also, you'd often see the second line written, `"Goodnight, #{ name }"` or `"Goodnight, %s" % name`. – Cary Swoveland Jan 04 '15 at 19:27

1 Answers1

15

When you define a function in Ruby at the global scope in this way, it technically becomes a private method of the Object class, which is the base class that everything inherits from in Ruby. Everything in Ruby is an object, so it is indeed true that you have defined a method.

def say_goodnight(name)
    result = "Goodnight, " + name
    return result
end

Object.private_methods.include? :say_goodnight
=> true

Because it is defined as a method with private visibility on Object, it can only be called inside objects of the class on which it's defined or subclasses. So why does it appear to be available globally?

Basically, the Ruby program itself defines an instance of Object called main, which serves as the top-level scope where your method was defined. So if you think of your program as running inside main (which is an Object) its private methods are available for use.

# In irb:
self
=> main
self.class
=> Object
self.private_methods.include? :say_goodnight
=> true

Addendum: This answer which further explains how main is defined and implemented.

Update for Ruby >= 2.3

Noted in the comment thread, later versions of Ruby would define the method Object#say_goodnight in this example with public visibility rather than private. This behavior appears to have changed between Ruby 2.2.x and 2.3.x, but does not affect method exposure.

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390