クラス変数・クラスメソッド

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

Rubyのクラス変数・クラスメソッドとは、CやPHPでの静的プロパティ・静的メソッドと同様のものです。
インスタンス(オブジェクト)に対する操作ではなくて、クラスそのものに対する操作を行うメソッドとなります。

スポンサーリンク

インスタンスを生成する利点は、インスタンスに固有のデータを扱うことができる点です。
しかし、データによっては、インスタンスに固有ではなく、すべてのインスタンスで共通して使うようなデータもあります。
共有して使うものに関しては、クラス変数やクラスメソッドを定義します。

クラス変数

クラス変数は、他言語では、静的プロパティ、静的メンバ変数、スタティック変数などとも呼びます。
クラスメソッドは、静的メソッド、静的メンバ関数、スタティックメソッドなどとも呼びます。
CやPHPの場合ですと、staticキーワードで宣言しますね。

以下、クラス変数とクラスメソッドを用いた例です。
プロフィールを作成した人数(Profileクラスから生成したインスタンスの数)を求めるために、クラス変数とクラスメソッドを用いています。
プロフィールの人数は、どのインスタンスからも共有すべき情報ですので、データがクラスに属するようにします。

クラス変数とクラスメソッドの定義の書き方

class Profile
    @@count = 0    # 人数
    
    def initialize(name_one)
        @name = name_one
        @@count += 1    # プロフィールが作成されるたびに人数をカウントアップ
    end
    
    # 人数を取得するクラスメソッド
    def Profile.count
        return @@count
    end
    
    # 名前の参照と変更
    attr_accessor :name
end
 
# Tommyのプロフィール作成(1人目)
tom = Profile.new("Tommy")
puts tom.name
 
# Williamのプロフィール作成(2人目)
wil = Profile.new("Wiliam")
puts wil.name
# 綴り間違い。Williamに訂正する
wil.name = "William"
puts "collect: #{wil.name}"
 
# Saekoのプロフィール作成(3人目)
saeko = Profile.new("Saeko")
puts saeko.name
 
puts "total: #{Profile.count} people"    # ここまでの人数確認
 
# Hirosiのプロフィール作成(4人目)
hirosi = Profile.new("Hirosi")
puts hirosi.name
 
puts "total: #{Profile::count} people"    # ここまでの人数確認

実行結果

Tommy
Wiliam
collect: William
Saeko
total: 3 people
Hirosi
total: 4 people

インスタンスが生成されるたびに(initializeで初期化が行われるたびに)、人数(@@countで表すクラス変数)を、カウントアップしています。
また、人数を参照するのは、どのインスタンスからも共通の機能になりますから、人数を取得するクラスメソッドを、「Profile.count」というクラスメソッドで定義しています。(Profile.count()と括弧をつけても良い)

ほかのクラスメソッド定義の書き方

また、クラスメソッドの定義の仕方は、

class Profile
  ・・・
  def Profile.count
    return @@count
  end
end

のほかにも、

class Profile
  ・・・
  def self.count
    return @@count
  end
end

という書き方もできます。
selfを用いれば、クラス名を、クラスメソッド定義で直に書くことを避けれます。

特異クラスを使ったクラスメソッド定義

また、特異クラスを使ったクラスメソッドの定義の書き方も可能です。
ただし、@@countをreturnしようとしたら、NameErrorが出ました。
@@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」という書き方は、特異クラスと呼ばれます。
Rubyでは、Profileというクラス自体もオブジェクト(Classクラスのインスタンス)であり、上のように特異クラスのなかで特異メソッドを定義する書き方も可能です。
Profileクラスというオブジェクトの特異メソッド、countを定義するという意味で、すなわち、クラスメソッドとはクラスの特異メソッドと同義。
特異メソッド、特異クラスに関しては、もう少ししっかり勉強する。

「def Profile.count」、または「def self.count」の書き方が簡単だと思います。
「def Profile.count」というクラスメソッドの書き方ですと、クラス名が変更したときに、クラスメソッドの部分の変更も必要となります。
ただ、クラス名が付いていることで、直感的にクラスメソッドであることが分かりやすいというメリットもありますので、必要に応じて、「クラス名.メソッド名」と「self.メソッド名」の2種類の書き方を使い分けると良いかもです。

あと、クラスメソッドを利用する際には、「Profile.count」のほか「Profile::count」という書き方も可能です。
PHPに慣れてるとこっちの書き方に馴染みがありますね。

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