0

Suppose I have the following simple class:

class C
  p self # => C

  def self.foo
    puts "foo"
  end

  def bar
    puts "bar"
  end
end

p C.foo # => "foo"
p C.bar # => "`<main>': undefined method `bar' for C:Class (NoMethodError)"

I know that self.foo defines foo to be an instance method inside the singleton class of C.

Why does the second method not get defined inside the singleton class of C like the first one? self is still C when this method is defined.

2 Answers2

1

it's a convention of the ruby language. (conceptually you can think of this like you think about static methods in Java. they are not associated with any instance of the class but with the class itself)

bar is going to be a method on objects instantiated from C. self.bar is going to be a method on C itself.

What's interesting in Ruby is that C class itself is an object (so the class definition that you can use to build objects is an object itself). That's where the self comes from (i.e. define this on myself vs define this from objects that will be built using me as a blueprint) Read more on this: Ruby craziness: Class vs Object?

Community
  • 1
  • 1
Mircea
  • 10,216
  • 2
  • 30
  • 46
  • I know that `C` is an object. I'm just confused about where methods are defined by default. If they're defined on `self`, then the `bar` method should be defined on the class `C` like the first method. –  Oct 14 '15 at 20:20
  • you are confused about 'self' ... self changes as the context changes. – jjk Oct 14 '15 at 20:29
  • 1
    It's just the way the ruby `def` keyword works, it's built into ruby to work this way. `def` will define an instance method in just `def method_name`, but a singleton class method with `def someclass.method_name`. It's just how `def` works. Because most of the time instance methods are what you want, they are the typical kind of method you are defining, so it's what `def` does. Just how ruby was designed to work, I see how you're trying to reason it out consistently, perhaps it's not consistent, it's just how ruby was designed. – jrochkind Oct 14 '15 at 20:37
  • think about C as a blueprint. everything you put in there (without def) alters the blueprint. when you build a new object via C.new you get what the blueprint defines. when you define things with self in front think about it like you are defining some operations that are related to the blueprint but are not captured in the blueprint itself. – Mircea Oct 14 '15 at 20:41
1

It works similarly to message sends and constant lookup:

  • The general format of a message send is foo.bar, which sends the message bar to foo. If you leave out foo, the message will be sent to the default receiver (which is self).
  • The general format of a constant lookup is Foo::Bar, which looks up the constant Bar in the module Foo. If you leave out Foo, the constant will be looked up in the default constant context (or cref).
  • The general format of a method definition is def foo.bar, which defines the method bar in the singleton class of foo. If you leave out foo, the method will be defined in the default definition context (or default definee):

    • At the top-level, the default definee is Object. (Also, the methods become private.)
    • Within a module declaration body, the default definee is self (and not self's singleton class, like you assumed!)
    • Within a method body, the default definee is the syntactically enclosing module. (Put another way: def doesn't change the default definee.)
    • instance_eval changes the default definee to the receiver's singleton class
    • class_eval changes the default definee to the receiver
Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • [default definition context](http://yugui.jp/articles/846) made it a lot clearer. –  Oct 15 '15 at 12:52