8

When I implemented an "instance of"/singleton type pattern, RubyMine notified that using class variables were considered bad form.

The only information I came across is that using class variables can make inheritance a bit squirrelly. Is there any other reason why the following code would give me problems?

class Settings
  private_class_method :new
  attr_accessor :prop1
  attr_accessor :prop2

  @@instance = nil

  def Settings.instance_of
    @@instance = new unless @@instance
    @@instance
  end
  def initialize
    @prop2 = "random"
  end
end

Also, is there a better way, Ruby-wise, to achieve the same objective to ensure only a single instance?

sawa
  • 165,429
  • 45
  • 277
  • 381
randall
  • 475
  • 1
  • 6
  • 14
  • 1
    Possible duplicate of [What is the correct way of ensuring a single instance of a class?](http://stackoverflow.com/questions/2310007/what-is-the-correct-way-of-ensuring-a-single-instance-of-a-class) – lurker Nov 17 '15 at 16:48
  • The body of your method `Settings.instance_of` can be simplified to `@@instance ||= new`. – sawa Nov 17 '15 at 16:51
  • 1
    You're asking two different questions here: (1) is the use of class variables bad (your question title)? and (2) how to create a single-instance class (your question content)? I cited a link for handling the single-instance idea. But what you have isn't a bad example of use of a class variable and they aren't *always* bad. They're just abused most of the time. I wouldn't categorize your example as "abuse". :) Another related example use of class variables might be instance counting. – lurker Nov 17 '15 at 16:52
  • This article at Practicing Ruby [Ruby and the singleton pattern don't get along](https://practicingruby.com/articles/ruby-and-the-singleton-pattern-dont-get-along) has been an invaluable reference to me. – Frank Joseph Mattia Nov 17 '15 at 16:57
  • Wow, thanks for all the feedback - and so quickly. I'll read over the links. Also, thanks @lurker for the detailed info – randall Nov 17 '15 at 17:32
  • Also @sawa for the optimization :-) – randall Nov 17 '15 at 17:33

2 Answers2

7

The problem with class variables in Ruby is that when you inherit from a class then the new class does not get a new copy of its own class variable but uses the same one that it inherited from its superclass.

For example:

class Car
  @@default_max_speed = 100
  def self.default_max_speed
    @@default_max_speed
  end
end

class SuperCar < Car
  @@default_max_speed = 200 # and all cars in the world become turbo-charged
end

SuperCar.default_max_speed # returns 200, makes sense!
Car.default_max_speed # returns 200, oops!

The recommended practice is to use class instance variables (remember that classes are simply objects of class Class in Ruby). I highly recommend reading Chapter 14 of Eloquent Ruby by Russ Olsen, which covers this topic in detail.

hp4k
  • 356
  • 2
  • 9
  • Thanks for the feedback. That's pretty much what I found in my research, but this is a nice succinct description. – randall Nov 17 '15 at 17:30
-2

Are Ruby class variables bad? Like any subjective matter it depends upon your point of view. There is a broad literature on the subject of global variables of which a singleton class is essentially a form. Being able to call up things containing state inside a method which are invisible in the invocation thereof tends to make understanding things difficult and maintenance problematic.

For Ruby-1.9.3 and later see the documentation for the better way:

http://ruby-doc.org/stdlib-2.2.3/libdoc/singleton/rdoc/Singleton.html

Replacing -2.2.3 with whatever version of Ruby you are running.

Basically:

Usage¶ ↑

To use Singleton, include the module in your class.

class Klass
   include Singleton
   # ...
end

Are singletons bad? Well I have been using ruby continuously since 2004 and I can only recall one occasion where I even considered using a singleton. And I cannot recall the details so I infer that I did not in fact do so. The need for a singleton is often a sign that the problem you are solving needs to be recast in a clearer formulation.

James B. Byrne
  • 1,048
  • 12
  • 27