When I need a singleton class in my Ruby code (for example, single logger for multiple classes) I usually use code like this:
class Parent_Singleton @singleton = nil def self.new @singleton || (@singleton = super) end end
This approach allows me to avoid using the module
Singleton (because I don’t want to use a special method
instance to get an object of this class, I just want to use the usual
Parent_Singleton.new in any part of my code to get my singleton object).
Another advantage of this approach is the ability to avoid using class variables
@@singleton which of course is a bad practice because of its behavior in inheritance. My code doesn’t have this issue:
class Child_Singleton < Parent_Singleton end p1 = Parent_Singleton.new p2 = Parent_Singleton.new c1 = Child_Singleton.new c2 = Child_Singleton.new p1 == p2 # => true c1 == c2 # => true p1 == c1 # => false p2 == c2 # => false
If I need to store some variable data in my class, it’s also not a problem:
class Parent_Class @singleton = nil @some_data = '' class << self def new @singleton || (@singleton = super) end def some_data @some_data end def some_data=(value) @some_data = value end end end class First_Child_Class < Parent_Class end class Second_Child_Class < Parent_Class end Parent_Class.some_data = 'Parent' First_Child_Class.some_data = 'First_Child' Second_Child_Class.some_data = 'Second_Child' puts Parent_Class.some_data # => Parent puts First_Child_Class.some_data # => First_Child puts Second_Child_Class.some_data # => Second_Child
So my question is: if this code is bad, what’s wrong with it? If this code is good, why the most of the examples worldwide suggest using either
Singleton module (with
instance method) or class variable-based singleton classes instead?