📜 ⬆️ ⬇️

And how do you create singletons in ruby?

How to create a singleton in ruby?
Personally, 4 ways come to my mind.


image


Method one: include Singleton


The standard library defines a module Singleton , which produces
Some actions on the class, in particular:



I guess this is a classic implementation of a singleton. Anyway, I would write
something like that, be I a java programmer. Nothing special, everything works.


Method two: module with module_function


The Module has a #module_function method that allows you to use
defined methods "on themselves". This approach is used, for example, in
Math Example:


 module M module_function def f :f end end Mf # ==> :f 

I would not recommend such a singleton implementation for several reasons:



By the way, you can use extend self for the same purpose instead of
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 extend self works differently, but I'm not sure that there is
some dangerous difference.


upd. still not very obvious. extend self causes the module to add itself to the list of connected modules (I don’t know how easy it is to write), and module_function creates copies of the methods. If specifically, look at the code:


 module M module_function def f :f end end class A include M end Mf # ==> :f # module_function     include A.new.send(:f) # ==> :f module M def f :TROLOLO end end A.new.send(:f) # ==> :TROLOLO Mf # ==> :f 

Method three: class / module only with class methods


 class MyClass def self.f :f end def self.g :g end end MyClass.f # ==> :f 

or so:


 class MyClass class << self def f :f end private def g :g end end end MyClass.f # ==> :f MyClass.g # ==> NoMethodError 

Of course, instead of class you can use module . In the above
style guide this approach is not recommended. Instead, recommend
module_function .


In my practice, this approach met most often. Personally, he always seemed to me
Some kind of scary crutch, but at the same time I like it more using
Singleton because MySingleton.do_something 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 end 

Now our singleton is just an Object instance with the methods we need:


 MySingleton.class # ==> Object 

Here are the problems here:



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 end 

At the same time, I repeatedly noticed that a person does not know what this
design. Actually, in Ruby, objects actually have two classes: one,
whose copy it is, and so on. "singleton class" - singleton class.


Surely you have seen 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. Object behavior
determined by the class to which it belongs. Therefore, we cannot determine
method on an object using def x.hey , we have to define it in the class. Here is
only if we do this, then all Object instances will have to
get the #hey method that we don't want. Therefore Ruby creates an "extra"
object class called 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
knew about the "singleton class". This is a very interesting side of Ruby, so I suggest
read about it yourself.


Actually, in short, the construction class << some_object "enters" into the class
singtona 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' 

')

Source: https://habr.com/ru/post/340006/


All Articles