特異クラスによるクラスメソッド定義・class << self ~ end

スポンサーリンク
スポンサーリンク
ライフスタイル関連のコンテンツ
お金 | 仕事 | 勉強 | プライベート | 健康 |
プログラミング関連のコンテンツ
C言語/C++入門 | Ruby入門 | Python入門 | プログラミング全般

Rubyのクラスは、Classクラスのインスタンスとなっていて、クラス自体も実はオブジェクト。
インスタンスであれば特異メソッドを定義できるわけで、Rubyのクラスメソッドとは、本当はClassクラスインスタンス(クラスオブジェクト)の特異メソッドとなっています。
特異メソッドは、特異クラスに追加する書き方が可能で、以下は特異クラス定義による、クラスの特異メソッド(すなわち、クラスメソッド)を定義する例。

スポンサーリンク

特異クラスにクラスの特異メソッド(クラスメソッド)を定義

class Profile
  @@count = 0
  def initialize(name_one)
    @name = name_one
    @@count += 1
  end
  def self.count
    @@count
  end
  attr_accessor :name
  class << self
    def singleton_count
      @@count
    end
  end
end
 
tom = Profile.new("Tom")
p tom
puts Profile.count
puts Profile.singleton_count
 
david = Profile.new("David")
p david
puts Profile.count
puts Profile.singleton_count
 
nick = Profile.new("Nick")
p nick
puts Profile.count
puts Profile.singleton_count

実行結果

#<Profile:0x283f9f8 @name="Tom">
1
1
#<Profile:0x283f930 @name="David">
2
2
#<Profile:0x283f8b8 @name="Nick">
3
3

ポイントは「class << self ~ end」

ポイントは、Profileクラスの中の、「class << self ~ end」の部分で、ここでのselfは、Profileインスタンス自体(Classクラスのインスタンス)を表している。
クラスの中でのインスタンスメソッド中のselfは、そのクラスのインスタンスを表すけれど、その場合のselfと特異クラス定義のselfは、意味が異なっています。

「class << self ~ end」のselfは、見慣れているクラスメソッド定義の仕方である、「def self.hoge ~ end」の場合のselfと同じ意味で、クラスオブジェクト自体を意味します。
selfの変わりに、クラス名自体(ここでは、Profile)を直書きして、「class << Profile ~ end」と書いても良いが、リファクタリングなどで修正箇所が増えるので、selfを使ったほうが楽だと思います。

「class Profile ~ end」の外側で特異クラス定義

以前、クラス変数・クラスメソッドで、「class Profile ~ end」定義の外側で、Profileの特異クラスを呼び出し、クラスの特異メソッド(クラスメソッド)を追加しようとしたら、クラス変数「@@count」へのアクセスの仕方が分からなかった。
具体的には、以下のようなコード。

class Profile
  ・・・
end
 
class << Profile
  def count
    put "hello"
    # return @@count #=> これはNameErrorとなった。
    #warning: class variable access from toplevel singleton method
    #NameError: uninitialized class variable @@count in Object
  end
end

今回のように、「class Profile ~ end」の中に、「class << self ~ end」と特異クラスを定義する書き方だと上手く行きました。
上の例の場合でも、@@countにアクセス可能なのかどうか、可能であればその方法を調べる。

スポンサーリンク
 
スポンサーリンク