How do you create singletones in Ruby?
How to create a singleton in Ruby?
Personally, 4 ways come to mind.

Method One: include Singleton
The standard library defines a module Singletonthat performs
some actions on the class, in particular:
- Makes
.newprivate - Adds
.instancethat creates and / or returns an instance - Overrides
#dupand#cloneso that they cause an error
I guess this is a classic singleton implementation. In any case, I would write
something like this if I were a Java programmer. Nothing special, everything works.
Method two: module with module_function
There Moduleis a method #module_functionthat allows you to use the
defined methods on your own. This approach is used, for example, in Math. Example:
module M
module_function
def f
:f
end
end
M.f # ==> :fI would not recommend such a singleton implementation for several reasons:
- This still remains a mixin, which can be included in another
class / module. This, of course, is not scary, but something is wrong here. Private methods can only be made with crutches, as module_function
creates a public copy of the method in itself. I immediately came up with just this:module M module_function def f g end def g 'hello' end singleton_class.send(:private, :g) end M.f # ==> 'hello' M.g # ==> NoMethodError- (Personal reason) Modules using
module_functionin my opinion should
be a collection of stateless methods to help in something. Accordingly, itinclude MyModulewill be used only to make methods
available in the current module without resorting toMyModule. This
usage scenario is provided in "The Ruby Programming Language" withMath
By the way, you can use for the same purpose extend selfinstead module_function. This will eliminate the problem of private methods. But let's say the
notorious ruby-style-guide does not approve of this approach (link:
https://github.com/bbatsov/ruby-style-guide#module-function )
I think it’s obvious that it extend selfworks differently, but I’m not sure that there is
any dangerous difference.
upd. still not very obvious. extend selfmakes the module add itself to the list of connected modules (I don’t know how simple it is to write), but module_functioncreates copies of methods. Specifically, look at the code:
module M
module_function
def f
:f
end
end
class A
include M
end
M.f # ==> :f
# module_function делает методы приватными в include
A.new.send(:f) # ==> :f
module M
def f
:TROLOLO
end
end
A.new.send(:f) # ==> :TROLOLO
M.f # ==> :fMethod three: class / module with class methods only
class MyClass
def self.f
:f
end
def self.g
:g
end
end
MyClass.f # ==> :for so:
class MyClass
class << self
def f
:f
end
private
def g
:g
end
end
end
MyClass.f # ==> :f
MyClass.g # ==> NoMethodErrorOf course, classyou can use instead module. In the aforementioned
style guide, this approach is not recommended. They recommend it instead module_function.
In my practice, this approach was most often encountered. Personally, it always seemed to me like
some kind of scary crutch, but at the same time I like it more than use Singleton, because MySingleton.do_somethingIt looks more attractive to me MySingleton.instance.do_something.
Create an instance of Object
Recently, I constantly use this approach:
MySingleton = Object.new
class << MySingleton
def f
g
end
private
def g
puts 'hello'
end
endNow our singleton is just an instance Objectwith the methods we need:
MySingleton.class # ==> ObjectHere are the problems:
- We can use the
#clone/#dup. Solution: override them as
done inSingleton - When inspecting an object, we get something like . Solution: override methods and . By the way, the
ruby-style-guide recommends doing this on all "own" (local? Ca
n't find the word) classes. Link: https://github.com/bbatsov/ruby-style-guide#define-to-s
##to_s#inspect - they write that this approach has problems with generating documentation. I
can not confirm or deny, because I do not use generators. Link:
https://practicingruby.com/articles/ruby-and-the-singleton-pattern-dont-get-along
A small digression: class << self
I think everyone saw the syntax:
class MyClass
class << self
def do_something_on_class
...
end
end
def do_something_on_instance
...
end
endAt the same time, I have repeatedly noticed that a person does not know what this
design means . Actually, in Ruby, objects actually have two classes: the one
whose instance it is, and the so-called. "singleton class" - singleton class.
Surely you saw examples where we define methods directly on objects.
Something like this:
x = Object.new
def x.hey
'hey'
end
x.hey # ==> 'hey'In a class-oriented OOP, an object does not have its own methods. The behavior of an object is
determined by the class to which it belongs. Therefore, we cannot define a
method on an object with def x.hey, we must define it in a class. But
if we do this, then all instances Objectwill have to
get a method #heythat we don’t want. Therefore, Ruby creates an “extra”
class for the object, called a singleton class. You can get it using the method #singleton_class. In general, I got carried away and probably only confused those who did not
know about the "singleton class". This is a very interesting side of Ruby, so I suggest
reading about it yourself.
Actually, in short, the design class << some_object"enters" into the
singleton class . Compare:
class A # enter class A scope
def hey
'hey'
end
end
class << A # enter class A singleton class scope
def hey
'hello'
end
end
A.new.hey # ==> 'hey'
A.hey # ==> 'hello'Only registered users can participate in the survey. Please come in.
Well ... how?
- 56.6% 1 option (Singleton) 34
- 11.6% 2 option (module_function) 7
- 23.3% 3 option (class methods) 14
- 5% 4 option (Object.new) 3
- 11.6% Custom 7