Explain singleton methods and singleton classes in Ruby

Time:2021-11-29

singleton method

Ruby allows you to add methods to a single object. This method that works only for a single object is called a singleton method

Sample code

?
1
2
3
4
5
6
7
8
9
10
11
12
str = “just a regular string”
 
def str.title?
  self.upcase == self
end
 
str.title? # => false
str.methods.grep(/title?/) # => [:title?]
str.singleton_methods  #=> [:title?]
 
str.class # => String
String.title? #=> NoMethodError

In addition, in addition to the definition methods used above, you can also use object #define_ singleton_ Method method to define a singleton method

Singleton method and class method

In the previous notes, it is said that in ruby, classes are also objects, and class names are just constants. Therefore, calling methods on classes is actually the same as calling methods on objects:

The essence of a class method is that it is a single method of a class. In fact, if you compare the definition of a single method with that of a class method, you will find that they are actually the same
 

?
1
2
def obj.a_singleton_method; end
def MyClass.another_class_method; end

Both use the def keyword for definition

?
1
2
3
def object.method
  #Method subject
end

The above object can be a reference to the * object, a constant class name, or self.

Class macro attr_ accessor

Ruby objects have no attributes. If you want to get something like attributes, you need to define a read method and a write method (that is, set and get methods in Java and objc). The most direct way is as follows:

Sample code

?
1
2
3
4
5
6
7
8
9
10
11
12
class MyClass
  def my_attribute=(value)
    @my_attribute =value 
  end
  def my_attribute
    @my_attribute
  end
end
 
obj = MyClass.new
obj.my_attribute = ‘x'
obj.my_attribute  #=> ‘x'

However, in the above way, if there are many attributes, there will be a place for repeat yourself. At this time, the following three class macros can be used:

  • Module#attr_ The reader generates a read method
  • Module#attr_ The writer generates a write method
  • Module#attr_ Accessor generates both read and write methods

Sample code

?
1
2
3
class MyClass
  attr_accessor :my_attribue
end

Is this much simpler? Of course, the usage (read and write) is consistent with the above implementation.

Single piece

We know that the search order of object methods in ruby is: first to the right, and then up. It means to find the class of the object to the right, try to find it in the instance method of the class, and if not, continue to find it along the ancestor chain.

The previous article introduced singleton methods. Singleton methods refer to those methods that are only effective for an object. If a singleton method is defined for an object, what should be the search order of the singleton method?

?
1
2
3
4
5
6
7
class MyClass
  def my_method; end
end
 
obj = MyClass.new
 
def obj.my_singleton_method; end

Firstly, the singleton method will not be in obj, because obj is not a class. Secondly, it is not in MyClass. In that case, all myclasses should be able to share and call this method, so it will not form a singleton class. Similarly, a singleton method cannot be in a position in the ancestor chain (similar to superclass: object). The correct position is in the singleton class. This class is actually the one we get when we ask the object about its class (obj. Class) in IRB. The difference is that this class is slightly different from ordinary classes. It can also be called metaclass or eigenclass.

Open singleton class

Ruby provides two methods to obtain the reference of singleton class. One is to use the traditional keyword class with special syntax

FA Yi
 

?
1
2
3
4
5
6
7
8
9
class << an_object
  #Own code
end
 
obj = Object.new
singleton_class = class << obj
  self
end
singleton_class.class # => Class

Another method is through object #singleton_ Class method to obtain the reference of the singleton class:

Method II

?
1
“abc”.singleton_class  # => #<Class: #<String:0xxxxxx>>

 
Properties of singleton class

  • Each singleton class has only one instance (the reason why it is called a singleton class) and cannot be inherited
  • A singleton class is where the singleton methods of an object live
  • Method lookup after introducing singleton class

Based on the above basic understanding of singleton class, after introducing singleton class, Ruby’s method search method should not start from its class (ordinary class), but from the singleton class of the object. If the desired method is not found in the singleton class, it will start along the class (ordinary class) and then find it in the ancestor chain. In this way, after the singleton class, everything returns to the order when we did not introduce the singleton class.

You can verify it by yourself through the following code

?
1
2
3
4
5
6
7
8
9
class C
  def a_method
    C#a_method()'
  end
end
 
class D < C; end
 
obj = D.new

Open singleton class to define singleton method

?
1
2
3
4
5
6
7
class << obj
  def a_singleton_method
    ‘obj#a_singleton_method()'
  end
end
 
obj.singleton_class.superclass #=> D