Difference Between 'Self.Method_Name' and 'Class << Self' in Ruby

Difference between 'self.method_name' and 'class self' in Ruby

The class << self notation opens up the eigenclass of an object. An eigenclass is an anonymous class that stores instance-specific behaviour. In the case of a class an eigenclass is sometimes called a metaclass.

Ruby uses eigenclasses to implement so called 'class methods' (also called static methods).

A Class (as moritz stated) is also an Object in Ruby and in so far as it is an object it also has a class. The class of a class in Ruby is called Class.

A 'class method' in any language is a method in which a class is the receiver - that is the method is directly invoked on the class itself.

However in order for a method to be invoked on a receiver that method must be defined on the class of that receiver. In the case of classes a 'class method' could be implemented as an instance method on the Class class.

But defining an instance method on Class would mean that ALL classes get access to that class method which is not ideal.

Enter the eigenclass, as stated before, the eigenclass for an object is a special class that stores the methods unique to that object. In the case of classes the eigenclass subclasses the Class class and is the direct class of the class.

'class methods' in Ruby therefore are just 'instance methods' defined on the class's eigenclass.

The def MyClass.my_method notation actually defines my_method on the eigenclass of MyClass. If you use this notation you can get by (for a while) without actually understanding eigenclasses since you can trick yourself into thinking it is just Ruby's way of defining 'static methods' and continue thinking Ruby's class model is similar to Java's. However, the class << self notation allows no such interpretation and you must come to terms with the reality of eigenclasses.

In summary, 'class methods' are actually 'instance methods' defined on the eigenclass and the class << self gives you access to the eigenclass.

For more reading check out these links:

http://banisterfiend.wordpress.com/2008/11/25/a-complete-ruby-class-diagram/

http://banisterfiend.wordpress.com/2008/10/25/the-secret-life-of-singletons/

http://www.klankboomklang.com/2007/09/21/the-singleton-class/

class self vs self.method with Ruby: what's better?

class << self is good at keeping all of your class methods in the same block. If methods are being added in def self.method form then there's no guarantee (other than convention and wishful thinking) that there won't be an extra class method tucked away later in the file.

def self.method is good at explicitly stating that a method is a class method, whereas with class << self you have to go and find the container yourself.

Which of these is more important to you is a subjective decision, and also depends on things like how many other people are working on the code and what their preferences are.

What does `def self.function` name mean?

Contrary to other languages, Ruby has no class methods, but it has singleton methods attached to a particular object.

cat = String.new("cat")
def cat.speak
'miaow'
end
cat.speak #=> "miaow"
cat.singleton_methods #=> ["speak"]

def cat.speak creates a singleton method attached to the object cat.

When you write class A, it is equivalent to A = Class.new :

A = Class.new
def A.speak
"I'm class A"
end
A.speak #=> "I'm class A"
A.singleton_methods #=> ["speak"]

def A.speak creates a singleton method attached to the object A. We call it a class method of class A.

When you write

class A
def self.c_method
'in A#c_method'
end
end

you create an instance of Class(*). Inside the class definition, Ruby sets self to this new instance of Class, which has been assigned to the constant A. Thus def self.c_method is equivalent to def cat.speak, that is to say you define a singleton method attached to the object self, which is currently the class A.

Now the class A has two singleton methods, that we commonly call class methods.

A.singleton_methods
=> ["c_method", "speak"]

(*) technically, in this case where A has already been created by A = Class.new, class A reopens the existing class. That's why we have two singleton methods at the end. But in the usual case where it is the first definition of a class, it means Class.new.

what does class self mean in Rails?

That is the same as

class Post < ActiveRecord::Base

def self.search(q)
# Class Level Method
# search from DB
end

def search2(qq)
# Instance Level Method
# search from DB
end
end

Class methods work on the class (e.g. Post), instance methods works on instances of that class (e.g. Post.new)

Some people like the class << self; code; end; way because it keeps all class level methods in a nice block and in one place.

Others like to prefix each method with self. to explicitly know that is a class method not an instance method. It's a matter of style and how you code. If you put all class methods in a block like class << self, and this block is long enough, the class << self line might be out of your editor view making it difficult to know that you are in the class instance block.

On the other hand, prefixing each method with self. and intermixing those with instance methods is also a bad idea, how do you know all the class methods while reading your code.

Pick an idiom which you prefer for your own code base but if you work on an open source project or you collaborate on someone else's code, use their code formatting rule.

Trying to understand use of self.method_name vs. Classname.method_name in Ruby


def before_create
self.hashed_password = User.hash_password(self.password)
end

In this example, User.hash_password calls the hash_password method on the class User, whereas self.hashed_password= calls the hashed_password= method on this particular instance of User.

If you replace User.hash_password with self.hash_password, Ruby would complain with a NoMethodError, because no instance method by the name of hash_password exists in the class User. You could replace it with self.class.hash_password, though.

If you replace self.hashed_password= with simply hashed_password=, Ruby would create a local variable named hashed_password, rather than call the instance method hashed_password=. You need to explicitly add self if you want to call attribute writers.

The self in the method definition (def self.hash_password) makes hash_password a class method instead of an instance method. In this context, self refers to the class. In the context of an instance method, self refers to an instance.

Using self in modules

The difference is that first example defines module method called preview, and second example defines mixin method preview.

So that if you include first module into a class, you'll be able to call this method on the class (whereas calling the method on the class instance would cause the error), while including the second module into the class will allow you to call the method on class' instances, but calling the method on the class itself will cause

NoMethodError: undefined method preview for Foo:Class

Regarding conflicts basing on the same method name in class and module included to it. Answer to this question lays in Ruby method lookup, which is following:

  1. Methods from the object's singleton/meta/eigen class
  2. Methods from prepended modules (Ruby 2.0+ feature)
  3. Methods from the object's class
  4. Methods from included modules
  5. Methods from the class hierarchy (superclass and its ancestors)

Method lookup stops, when the method is found.

With prepend the mixin method will have precedence in method lookup;

With include method defined in class has the precedence in method lookup.

So no conflicts are possible.

def self.methodName vs def methodName

Assuming User model

  1. Instance methods

     def methodName

    #do something
    end

to call this method use

User.new.methodName
  1. Class Methods

    def self.methodName #OR User.methodName
    #do something
    end

to call this method use

User.methodName

Yield in class self in class method

It's a little bit weird, but OK if you are exploring Ruby.

class Person
puts "evaluating Person's body ..."
def self.mega_methods
puts 'in Person#self.mega_methods, about to yield ...'
yield
end
end

class Tom < Person
puts "evaluating Tom's body ..."
print 'Tom.singleton_methods : '; p Tom.singleton_methods
mega_methods do
puts 'in Tom, about to define self.hiya!'
def self.hiya!
puts 'hiYA!'
end
end
print 'Tom.singleton_methods : '; p Tom.singleton_methods
end

Tom.hiya!

Execution :

$ ruby -w t.rb 
evaluating Person's body ...
evaluating Tom's body ...
Tom.singleton_methods : ["mega_methods"]
in Person#self.mega_methods, about to yield ...
in Tom, about to define self.hiya!
Tom.singleton_methods : ["mega_methods", "hiya!"]
hiYA!

Note that the exclamation point in the name of a method is, by convention, reserved for destroying methods, such as String#sub! which modifies the receiver string.

See also What does def `self.function` name mean?

It's all about self !

class Person2
def self.mega_methods
print 'in Person2 self='; p self
class << self
print 'in class << self self='; p self
yield
end
end
end

class Tom2 < Person2
mega_methods do
puts "in Tom2, about to define self.hiya! for self=#{self}"
def self.hiya!
puts 'hiYA!'
end
def hi
puts 'hi'
end
end
end

print 'Tom2.singleton_methods : '; p Tom2.singleton_methods
print 'Tom2.instance_methods : '; p Tom2.instance_methods(false)
Tom2.hiya!
Tom2.new.hi

Execution :

$ ruby -w t2.rb 
in Person2 self=Tom2
in class << self self=#<Class:Tom2>
in Tom2, about to define self.hiya! for self=Tom2
Tom2.singleton_methods : ["mega_methods", "hiya!"]
Tom2.instance_methods : ["hi"]
hiYA!
hi

How to create a private class method?

private doesn't seem to work if you are defining a method on an explicit object (in your case self). You can use private_class_method to define class methods as private (or like you described).

class Person
def self.get_name
persons_name
end

def self.persons_name
"Sam"
end

private_class_method :persons_name
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name

Alternatively (in ruby 2.1+), since a method definition returns a symbol of the method name, you can also use this as follows:

class Person
def self.get_name
persons_name
end

private_class_method def self.persons_name
"Sam"
end
end

puts "Hey, " + Person.get_name
puts "Hey, " + Person.persons_name


Related Topics



Leave a reply



Submit