singletonを調べてみる

「シングルトン(singleton)」という言葉が気になっていろいろ読み漁っている。もともとRHGのクラスの実装の解説を読んでいたところで「特異メソッド」というのが出てきて、これは一体なんだと思ったというのがきっかけ。ヘンな取っ掛かりだ。

RHGは相変わらずiPhoneで拾い読みしているのだけど(たぶんそろそろ全部に目を通したけど何せiPhone、自分が何を読んだか、どこを読んだかもよく分からない)、カレーを食う手が止まってしまった。特異クラスがふつうのクラスと実装上なにが違うのとかというとSINGLETONフラグが立ってるんだという。よくワカランぞ。

関連しそうな語句を拾うと、

  • 特異クラス
  • 特異メソッド
  • シングルトン
  • リフレクション
  • 動的OOP
  • クラスもオブジェクト
  • クラスメソッド

というあたり。いろいろ読んだ範囲で、この辺の関係を解説っぽくリプロデュースすると、こんな感じ。

特異メソッドというのは特定のオブジェクト(インスタンス)に対してのみ定義されたメソッド。Rubyはクラスもオブジェクトなので、クラスメソッドというのは、実はクラスオブジェクトに対して定義された特異メソッド。

特異クラスはSINGLETONフラグが立っているクラスで、インスタンスが1つしか生成できないシングルトンを実現している。なんで特異クラスが必要かというと、えーと、何だっけ……。そうか特異メソッドを実現するためか。

RHGのクラスの章によれば、継承の段数を1つ増やして特異クラスを挿入することで、特異メソッドというのが実現できる。ような気がする。

str = "Hey"
str2 = "Ho"

def str.upcase
  self.downcase
end

puts str.upcase   # "hey"
puts str2.upcase  # "HO"

あるいは、別の書き方だと、

str = "Hey"
str2 = "Ho"

class <<str
  def upcase
    downcase
  end
end

puts str.upcase   # "hey"
puts str2.upcase  # "HO"

puts str.class # String
puts str2.class # String

この例ではstrというオブジェクトにメソッドを定義しているように見えるけど、実際にはStringクラスをスーパークラスに持つstrというオブジェクトではでもStringクラスでもなく、その下にこっそり挿入されててユーザーには直接見えない特異クラスに対してメソッドを定義しているってことなのか。

Rubyではクラスもオブジェクトで、しかも動的にいじれる。このへんのことをリフレクションとか呼ぶ。逆に、こういう動的なOOPを実現するにはクラスはオブジェクトで、しかもシングルトンとしていじれる必要がある。それでクラスオブジェクトを扱うクラスメソッドというのは特異メソッドとして実装されている。

デザインパターンとしてのシングルトン・パターンは、singleton.rbというライブラリを利用して使えるらしいけど、これはRubyを使ってシングルトン・パターンを利用するためのものであって、Ruby処理系の中でクラスやクラスメソッドを実装するために使っている特異メソッド特異クラス(SINGLETONフラグあり)とは直接関係していない。

なんか話が循環しているような。頭が悪すぎる。ビール飲みすぎたので寝よう。