Ruby Singleton Objects
Tags: rubytapasfreebies, design, designpatterns, featured
Published: 2020-11-08 18:24:53

---
title: Ruby Singleton Objects
published: true
date: 2020-10-09 18:31:39 UTC
tags: RubyTapasFreebies,design,DesignPatterns,featured
canonical_url: https://avdi.codes/ruby-singleton-objects/
---

Here’s another freebie from the deep [RubyTapas](https://www.rubytapas.com) stacks. This one is about a truth of object modeling that we don’t often talk about: not every object needs to have state. If an object has no state, there’s no need to have more than one of it. And for stateless objects, having a class just to generate a single instance may be superfluous!

**Director’s commentary:** In retrospect I’d tighten up the pacing on this one. And I hate that the ending monologue on the Singleton pattern has no illustration on the screen. Also, I really hope I don’t sound that bored in more recent videos.

<script src="https://fast.wistia.com/assets/external/E-v1.js" async></script>

 ![](https://fast.wistia.com/embed/medias/ph9yjzc6x8/swatch)

While I was at [Ruby DCamp](https://www.rubytapas.com/out/rubydcamp) a few weeks ago [Sandi Metz](https://www.rubytapas.com/out/sandi-metz) asked me to write a version of [Conway’s Game of Life](https://www.rubytapas.com/out/conways-life) in a semi-functional, stateless style. I decided to represent the concept of a “live cell” and a “dead cell” as two different kinds of object. The game grid would then be represented by a simple array of arrays, populated by live cells and dead cells.

I was all set to write a class for each…

```
class LiveCell
  # ...
end

class DeadCell
  # ...
end

```

…when it occurred to me: since this is a stateless implementation, there was no real need to have individual `LiveCell` objects for every live cell on the board. And the same goes for dead cells. Without any state, every instance would be exactly the same. And since the objects didn’t have any need for initialization, why even bother with classes?

Instead, I created the objects as singleton instances of the `Object` class. I assigned the instances to constants, so they would be available anywhere in the program. Then I used Ruby’s singleton class syntax to add methods to each one. Each object needed two methods: a `#to_s` method to represent the cell on an ASCII grid, and a method to determine what the next generation of its grid square would contain: either a live cell or a dead cell.

```
LIVE_CELL = Object.new
class << LIVE_CELL
  def to_s() 'o' end

  def next_generation(x, y, board)
    case board.neighbors(x,y).count(LIVE_CELL)
    when 2..3 then self
    else DEAD_CELL
    end
  end
end

DEAD_CELL = Object.new
class << DEAD_CELL
  def to_s() '.' end

  def next_generation(x, y, board)
    case board.neighbors(x,y).count(LIVE_CELL)
    when 3 then LIVE_CELL
    else self
    end
  end
end

```

Then I could just populate my grid with the same LIVE\_CELL and DEAD\_CELL  objects, over and over again.

```
[
 [DEAD_CELL, LIVE_CELL, LIVE_CELL, DEAD_CELL],
 # ...
]

```

This worked quite well, but I didn’t like the fact that the singleton objects had to be created in two steps. So I decided to see if I could create the object, assign it to a constant, and define methods on it, all in a single statement.

To accomplish this feat, I took advantage of the fact that Ruby allows variables and constants to be assigned inside parenthesized sub-expressions of a statement.

```
class << (LIVE_CELL = Object.new)
  def to_s() 'o' end

  def next_generation(x, y, board)
    case board.neighbors(x,y).count(LIVE_CELL)
    when 2..3 then self
    else DEAD_CELL
    end
  end
end

class << (DEAD_CELL = Object.new)
  def to_s() '.' end

  def next_generation(x, y, board)
    case board.neighbors(x,y).count(LIVE_CELL)
    when 3 then LIVE_CELL
    else self
    end
  end
end

```

The resulting syntax was a bit obscure, but it accomplished my purpose succinctly.

A class plays two roles in an [OO program](https://www.rubytapas.com/t/oop):

1. It provides a container for behavior that’s shared by many objects.
2. It acts as an _[object factory](https://www.rubytapas.com/out/factory)_, manufacturing new instances and  
ensuring they are initialized correctly.

When we have an object which does not need to share behavior with any others objects, and which requires no initialization, that renders both roles of a class superfluous. In cases like this, it can make more sense to just use a one-off [singleton object](https://www.rubytapas.com/out/ruby--singleton).

Another way to accomplish this is to use a [module](https://www.rubytapas.com/out/ruby--module) as our singleton object, and only define class-level methods on the module. Let’s update the example to use this approach instead.

```
module LiveCell
  def self.to_s() 'o' end

  def self.next_generation(x, y, board)
    case board.neighbors(x,y).count(LiveCell)
    when 2..3 then self
    else DeadCell
    end
  end
end

module DeadCell
  def self.to_s() '.' end

  def self.next_generation(x, y, board)
    case board.neighbors(x,y).count(LiveCell)
    when 3 then LiveCell
    else self
    end
  end
end

[
 [DeadCell, LiveCell, LiveCell, DeadCell],
 # ...
]

```

This is a perfectly legitimate way to implement singleton objects. Personally, I feel that using a singleton instance of `Object` is a little more intention-revealing, since modules are usually used as namespaces and as a means of sharing behavior. But I don’t feel that strongly about it. The main thing I hope to convey in this episode is simply that sometimes a singleton object is all we need, and when that’s all we need, that’s all we should use.

I should make one last point here: I’m talking about singleton _objects_, not the Singleton _Pattern_. The [Singleton Pattern](https://www.rubytapas.com/out/singleton) describes a way to control the construction of a particular class such that only one instance is ever constructed. Singletons following this pattern have often been used to manage a great deal of centralized state, a situation that can lead to a number of problems, including thread contention and proliferation of dependencies. The singleton objects we’ve defined here are stateless and more akin to the immutable singletons that Ruby provides like `true`, `false`, and `nil`. As such they are somewhat less prone to abuse.

Okay, enough for today. Happy hacking!