Rubyの特異クラス（singleton class）はsingletonパターンと無関係なものなのか？

発端は、「特異クラスから元のインスタンスを取り出せるか（ `Object#singleton_class` の逆ができるか）」と疑問に思ったこと。 `#instance` みたいなメソッドで取り出せるなら楽だと思ったが、それは正に `Singleton` モジュールがやっていることである。特異クラスはsingletonパターンに当てはまりそうなのに、 `Singleton` モジュールとは関係が無いのはなぜなのだろう？

※本記事は疑問点を書いているだけであり、自己解決はしていない。

## 基本知識
### singletonパターン
[Singleton パターン - Wikipedia](https://ja.wikipedia.org/wiki/Singleton_パターン)

> Singleton パターン（シングルトン・パターン）とは、オブジェクト指向のコンピュータプログラムにおける、デザインパターンの1つである。GoF (Gang of Four; 4人のギャングたち) によって定義された。Singleton パターンとは、**そのクラスのインスタンスが1つしか生成されないことを保証するデザインパターン**のことである。ロケールやルック・アンド・フィールなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される。

---

Rubyにおいては、クラスに [**`Singleton` モジュール**](https://docs.ruby-lang.org/ja/latest/class/Singleton.html)をmix-inするだけで作れる。標準ライブラリでの一例は [`Prime` クラス](https://docs.ruby-lang.org/ja/latest/class/Prime.html)。

```ruby
require 'prime'

Prime.ancestors
#=> [Prime, Singleton, Enumerable, Object, Kernel, BasicObject]

obj = Prime.new
#=> NoMethodError: private method `new' called for Prime:Class
obj1 = Prime.instance   #=> #<Prime:0xZZZZ>   # 新規作成
obj2 = Prime.instance   #=> #<Prime:0xZZZZ>
obj1.equal? obj2   #=> true
```

### 特異クラス
Rubyは全てのデータがオブジェクト、つまり何らかのクラスのインスタンスだが、加えて各オブジェクトは**自分専用のクラス**にも属する。（※例外は後述）

```ruby
obj1 = Object.new               #=> #<Object:0xXXXX>
obj2 = Object.new               #=> #<Object:0xYYYY>
IClass = obj1.class             #=> Object
SClass = obj1.singleton_class   #=> #<Class:#<Object:0xXXXX>>

class IClass   # class Object と同じ
	def foo
		p "Hello, an instance method!"
	end
end

class SClass   # class << obj1 と同じ
	def bar
		p "Hello, a singleton method!"
	end
end

obj1.foo   #=> "Hello, an instance method!"
obj2.foo   #=> "Hello, an instance method!"
obj1.bar   #=> "Hello, a singleton method!"
obj2.bar   #=> NoMethodError: undefined method `bar' for #<Object:0xYYYY>
```

`obj1` の特異クラス（定数 `SClass` に割り当てたもの）は**インスタンスとして `obj1` のみを持つ**ため、ここに追加したインスタンスメソッドは `obj2` など他のオブジェクトに対しては呼び出せない。

特異クラスの取得は上記のように [`Object#singleton_class`](https://docs.ruby-lang.org/ja/latest/method/Object/i/singleton_class.html) を使う。また、あるクラスが特異クラスかどうか調べるには、 [`Module#singleton_class?`](https://docs.ruby-lang.org/ja/latest/method/Module/i/singleton_class=3f.html) を使う。

```ruby
IClass.singleton_class?   #=> false
SClass.singleton_class?   #=> true
```

#### 例外1
`nil`, `true`, `false` の特異クラス（を取得しようとして返るクラス）は通常のクラス、つまりそれぞれ `NilClass`, `TrueClass`, `FalseClass` である。

```ruby
nil.singleton_class   #=> NilClass
```

#### 例外2
`Integer`, `Float`, `Symbol` クラスのインスタンスはどの特異クラスにも属さない。

```ruby
123.singleton_class   #=> TypeError: can't define singleton
```

## 疑問
上の例を見る限り、特異クラスはsingletonパターンの振る舞いをしているように見える。しかし実際は両者に隔たりがあり、できないことが存在する。

```ruby
obj1 = Object.new               #=> #<Object:0xXXXX>
SClass = obj1.singleton_class   #=> #<Class:#<Object:0xXXXX>>

# Singletonモジュールをmix-inしていないことが確認できる
SClass.ancestors   #=> [#<Class:#<Object:0xXXXX>>, Object, Kernel, BasicObject]

# 元のインスタンスを取得できない
SClass.instance   #=> NoMethodError: undefined method `instance' for #<Class:#<Object:0xXXXX>>
SClass.new        #=> TypeError: can't create instance of singleton class

# 例外1のオブジェクト（nilなど）は特異クラスを取得しても特異クラスが返らない
nil.singleton_class.singleton_class?   #=> false
nil.singleton_class.equal? nil.class   #=> true

# 逆に、Singletonモジュールをmix-inしたクラスのインスタンスは、特異クラスを取得すると元のクラスと異なる（これは当たり前？）
require 'prime'
Prime.singleton_class?    #=> false
s_inst = Prime.instance   #=> #<Prime:0xZZZZ>
s_inst.singleton_class    #=> #<Class:#<Prime:0xZZZZ>>
s_inst.singleton_class.equal? s_inst.class   #=> false
```

恐らく歴史的には「特異クラス」という考え方ができたのがsingletonパターンと無関係なのだろうが、関係を作ってもいいように思う。以下のようになっていると何か不都合があるのだろうか？

* 特異クラスが `Singleton` モジュールをmix-inする（またはそれに相当する動作をする）
	* `#instance` メソッドで元のオブジェクトを取得できる
* `Singleton` モジュールをmix-inしたクラスが特異クラスとして元のクラスを返す
	* つまり `#singleton_class` メソッドが `#class` メソッドのエイリアスになる
	* クラスに対する `#singleton_class?` メソッドも `true` を返す
* 例外1のオブジェクトのクラス（ `NilClass` など）はこれらを体現したものとなる
* いっそのこと `SingletonClass` クラスという形で統合する

```ruby:SingletonClassクラスの想像
# Classクラスの子クラスである
SingletonClass.ancestors
#=> [SingletonClass, Class, Module, Object, Kernel, BasicObject]

# 特異クラスを表す
Object.new.singleton_class   #=> #<SingletonClass:#<Object:0xAAAA>>
NilClass.class               #=> SingletonClass

# 唯一のインスタンスを返すメソッドを持つ
NilClass.instance   #=> nil

# singletonパターンのクラスはこのクラスのインスタンスとして作る
Prime = SingletonClass.new do
	# include Singleton は不要
end
Prime.instance   #=> #<Prime:0xPPPP>
```

## おまけ：発端の疑問の解決策
「特異クラスから元のインスタンスを取り出せる」ようにする方法は、以下のページで質問・回答されている。C拡張ライブラリを作る方法が最もきれいに思える。

[Retrieve a Ruby object from its singleton class? - Stack Overflow](https://stackoverflow.com/questions/54531270)