Reputation: 2623
In normal ruby code, I can normally omit self
:
class User
def greeting
# these 2 are the same:
puts "Hi, #{name}"
puts "Hi, #{self.name}"
end
end
but why are these 2 different:
# 1
class User
def self.greeting
# ...
end
end
# 2
class User
def greeting
# ...
end
end
Why can't I just omit the self
? What's the difference here to ruby code compiler's perspective?
I know #1 is class method definition (Singleton method definition) and #2 is instance method definition. But how did ruby work with context and self to arrive at this difference in method definition?
Upvotes: 1
Views: 484
Reputation: 110755
Methods defined on a class are instance methods:
class Animal
def dog
"woof"
end
def cat
"meow"
end
end
They are so-named because they respond to any instance of the class, meaning that their receiver must be an instance of the class:
Animal.instance_methods(false)
#=> [:dog, :cat]
animal = Animal.new
#=> #<Animal:0x00005bfb0c55ae98>
animal.dog
#=> "woof"
Animal.dog
#=> NoMethodError (undefined method `dog' for Animal:Class)
To define a method whose receiver is a class (a class method) we define the method on the class's singleton class. For the class Animal
we could write either of the following.
class Animal
class << Animal
def pig(n)
"#{n} little pigs"
end
end
end
Animal.methods(false)
#=> [:pig]
Animal.pig(3)
#=> "3 little pigs"
or
Animal.define_singleton_method(:pig) do |n|
"#{n} little pigs"
end
Animal.methods(false)
#=> [:pig]
Animal.pig(3)
#=> "3 little pigs"
The line class < Animal
1 changes the scope to Animal
's singleton class, causing the value of self
to change to that class as well.
So what does this have to do with the question, that is, defining methods def self.my_method ...
? The short answer is that there is no need to define methods in that way. Please be patient--I'll get to that.
Note that the method pig
, defined on Animal
's singleton class, is inherited by the singleton class of subclasses of Animal
:
class Swine < Animal
end
Swine.instance_methods & [:dog, :cat]
#=> [:dog, :cat]
Swine.methods & [:pig]
#=> [:pig]
We can also define methods on many unique objects. Consider animal
, an instance of Animal
:
animal.define_singleton_method(:rodent) do |n|
"I'm rodent ##{n}"
end
animal.rodent(3241)
#=> "I'm rodent #3241"
animal
is the only receiver to which this method will respond:
Animal.new.rodent(55)
#=> #NoMethodError (undefined method `rodent' for
# #<Animal:0x00005bfb0c530670>)
In fact, we can define methods on every object that has a singleton class, which is most objects:
str = "cow"
str.define_singleton_method(:greeting) { "moo" }
str.greeting
#=> "moo"
arr = [1,2]
arr.define_singleton_method(:greeting) { "I'm an array" }
arr.greeting
#=> "I'm an array"
module M; end
M.define_singleton_method(:greeting) { "I'm a module" }
M.greeting
#=> "I'm a module"
piggy = Animal.method(:pig)
#=> #<Method: Animal.pig>
piggy.define_singleton_method(:greeting) {
"I'm a singleton method" }
piggy.greeting
#=> "I'm a singleton method"
We can do this with all Ruby objects that have a singleton class. That comprises all objects except those having immediate values (objects passed by value), which include nil
, true
, false
, Integers, Symbols, and some Floats. In addition, objects that have been frozen (e.g., "Hi".freeze
) do not have a singleton class.
Suppose now we write
class Animal
def Animal.pig(n)
"#{n} little pigs"
end
end
or (same thing)
class Animal
def self.pig(n)
"#{n} little pigs"
end
end
(We're finally there!)
What is this new way of defining a method? It is in fact just a shorthand way of defining a method on Animal
's singleton class. Think of it as merely syntactic sugar. Just as writing 2 + 2
instructs Ruby to execute 2.+(2)
, Animal.
or self.
in the first line of the method definition merely instructs Ruby to execute the following.
class Animal
class << self
def pig(n)
"#{n} little pigs"
end
end
end
In other words, the creation of class method by writing def Animal.my_method...
or def self.my_method...
is not needed at all; it is there merely as a convenience for Ruby coders.
1 That line would generally be written class << self
, which is acceptable as self
equals Animal
when the line is executed. Using << self
is merely a convenience should the class be renamed.
Upvotes: 1
Reputation: 369614
First of all, it is important to understand that there is no such thing as class method or a singleton method in Ruby. There is only exactly one kind of methods: instance methods.
The real question is: what module is the method defined in?
["Singleton method" and "class method" are simply shorthand names that we use for "method that is defined in the singleton class" and "method that is defined in the singleton class of an object whose class is Class
".]
There are two forms of method definitions in Ruby:
def some_expression.some_name; end
and
def some_name; end
The first one will first evaluate the expression some_expression
and then define a method named some_name
inside the singleton class of the resulting object.
The second one will define a method named some_name
in what is called the default definee. The default definee is usually the closest lexically enclosing module definition. For example, in this case:
module Foo
module Bar
def foo
def bar; end
end
end
end
include Foo::Bar
foo
# At this point, `bar` will be defined, but where?
Here, bar
will be defined as an instance method of Foo::Bar
, because bar
is the closest lexically enclosing module definition. There is another lexical definition that is even closer, namely the method definition of foo
, but that is not a module definition.
A little bit more puzzling:
Foo = Class.new do
def foo; end
end
This will define foo
as an instance method of Foo
, even though technically this is not a module definition, it is "just" a block. However, that's why I wrote "usually" above: some methods can change the default definee, and Class::new
is one of those methods (similar to how, e.g. Object#instance_eval
changes the value of self
).
Another example:
def foo; end
In this case, there is no lexically enclosing module definition. At the top-level, the default definee is Object
but with a twist: the default visibility is also private
.
All of this is explained in greater detail in the brilliant blog post Three implicit contexts in Ruby by yugui.
Now, the only thing missing is: what does the expression self
evaluate to inside a module definition? Well, you can test it out if you want:
class Foo
p self
end
The answer is that inside a module definition, self
evaluates to the module being defined. (Kind of makes sense, does it?)
Therefore, in
class Foo
def self.foo; end
end
foo
is defined in the singleton class of Foo
.
Upvotes: 0
Reputation: 168269
In a method body, self
refers to the receiver. In lines 3..4 of the following, once the receiver is determined to be a User
instance (by the def greeting
syntax), self
refers to that instance.
class User
def greeting
puts "Hi, #{name}" # method body
puts "Hi, #{self.name}" # method body
end
end
In a class body, self
refers to the class. In lines 2, 4, 8, 10 of the following, the class is User
, so def self.greeting
is the same as def User.greeting
.
class User
def self.greeting # class body
# ...
end # class body
end
class User
def greeting # class body
# ...
end # class body
end
But I actually think your real issue is not what self
means, but rather what "an omitted receiver" means, in different contexts.
In method-calling syntax, an omitted receiver stands for self
. So the following two are the same:
name
self.name
In method-defining syntax, an omitted receiver stands for "any instance of the class". So the following two are not the same:
def User.greeting; ... end
def greeting; ... end
When you define an instance method, there is no explicit way to express "any instance of the class", so actually omission is mandatory.
Upvotes: 5
Reputation: 5552
self
is mandatory while defining class methods whereas without self keyword it will be treated as instance methods. class << self; end;
block also used to define numbers of class methods.
These methods are loaded when your class is loaded and above will help to distinguish them.
It will be simply like relating with real life example.
You have number of accounts having authentication provided on your computer, valid person with right password can enter inside account. Once you enter inside account, you do not need to mention who you are! It always count you the one who entered.
Upvotes: 0
Reputation: 1970
The self
is sometimes needed (otherwise it wouldn't exist at all). The first example you give is a case where it is redundant. Both of those method calls refer to the same method.
There are times when it is needed to distinguish between two different behaviours.
In your examples #1 and #2 the self
is used to make sure the method is defined on the class, rather than being on instances of the class. The self
isn't redundant in this case. This is the way that the Ruby interpreter knows where you want the method defined. It might be helpful to think about the self
in your very first example as a different thing to the self
in examples #1 and #2. It might be helpful to think of the self
in #1 and #2 as "class
"? They're the same keyword but how they are used is not directly interchangeable.
Another example of where it isn't redundant:
# user.rb
def method1
name = "Henry" # Sets a local variable called `name`
end
def method2
self.name = "Henry" # Sets the user's `name` attribute
end
Upvotes: 3
Reputation: 73100
In a class if you define a method on self, it defines it on the class. E.g.
class User
def self.greeting
"Hello User"
end
end
Then you can call
User.greeting
# => "Hello User"
If you define a method without self, then that method is defined for objects of that class. E.g.:
class User
def greeting
"Hello user"
end
end
Then you have to create a new user object to call greeting
.
user = User.new
user.greeting
# => "Hello user"
Upvotes: 0