【Ruby】クラスメソッドの書き方と使い方の基本

作成日: 更新日:

開発環境

  • Ruby version: ruby 3.1.2

Rubyのクラスメソッドとは

Rubyのクラスメソッドとは、クラスの特異メソッドのことです。 クラス自体に関連付けられたメソッドで、そのクラスのインスタンスではなく、クラスそのものに対して呼び出されます。 クラスメソッドは通常、クラスに関連するユーティリティ関数やファクトリメソッドを実装するために使用されます。 公式リファレンス:https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#class_method

Rubyのクラスメソッドの使いどころ

Rubyのクラスメソッドは基本的にクラス全体に関連する機能や操作を提供するためのものです。 クラスメソッドの一般的な使いどころとしては、オブジェクトのインスタンスを生成するための「ファクトリメソッドを定義」、「ユーティリティ関数の提供」や「カウンターの管理」など様々です。

Rubyのクラスメソッドの使い分け

Rubyのクラスメソッドの使い分けについては開発方針によっても異なります。 基本的には、クラスメソッドはクラス全体に関連する操作やデータ、ユーティリティを提供するために使われ、インスタンスメソッドはオブジェクト固有の振る舞いや相互作用を定義するために使われます。 そのため、クラスメソッドはクラス全体の情報を読み書きする場合に、インスタンスメソッドは個別に作成されたインスタンスの情報を読み書きする場合に使われる仕組みとして使い分けるのがおすすめです。

Rubyのクラスメソッドの書き方

Rubyのクラスメソッドの書き方をご紹介します。

メソッド定義の前に「self.」を付ける

メソッド定義の前に「self.」を付ける書き方です。

1# クラスの定義
2class SampelClass
3    # クラスメソッドの定義
4    def self.sample_class_method
5        puts "クラスメソッドを実行します。"
6    end
7end
8
9# クラスメソッドの呼び出し
10SampelClass.sample_class_method
11
12# =>クラスメソッドを実行します。

上記の例では、「sample_class_method」は「SampelClass」のクラスメソッドです。 クラスメソッドは、クラス自体に関連付けられているため、インスタンスを作成する必要はありません。

クラス定義内に「class << self ブロック」を使用する

クラス定義内に「class << self ブロック」を使用する書き方です。

1# クラスの定義
2class SampelClass
3    class << self
4        # クラスメソッドの定義
5        def sample_class_method
6            puts "クラスメソッドを実行します。"
7        end
8    end
9end
10
11# クラスメソッドの呼び出し
12SampelClass.sample_class_method
13
14# =>クラスメソッドを実行します。

ネストは一つ深くなりますが、「class << self」内でクラスメソッドを定義することにより、ブロック内のメソッドはクラスメソッドとして定義することができます。

Rubyのクラスメソッドの使い方

Rubyのクラスメソッドのよくあるパターンをサンプルコードを用いて使い方の解説をしていきます。

Rubyのクラスメソッドをクラスオブジェクトから実行するパターン

Rubyのクラスメソッドをクラスオブジェクトから実行するパターンです。

1# メソッドの定義
2class Exam
3    # 合計の合格ライン
4    def self.passing_total
5        400
6    end
7end
8
9# クラスメソッドの実行
10passing_total = Exam.passing_total
11
12# インスタンスメソッドの実行結果を出力
13puts(passing_total)
14
15# => 400

「Exam」クラスを定義してテストの合格点をクラスメソッドで定義をしています。 サンプルコードでは「Exam」クラスにドット(.)で「passing_total」を記述してクラスメソッドを呼び出し、合計の合格ラインを出力しています。

Rubyのクラスメソッドをインスタンスメソッドから実行するパターン

Rubyのクラスメソッドをインスタンスメソッドから実行するパターンです。

1# メソッドの定義
2class Exam
3    # インスタンスの初期化 
4    def initialize(scores)
5        @scores = scores
6    end
7    # 合計点数
8    def total_score
9        @scores.sum
10    end
11    # 合格点を超えているかの判定
12    def passed_total?
13        if total_score >= self.class.passing_total
14            "合格"
15        else
16            "不合格"
17        end
18    end
19    # 合計の合格ライン
20    def self.passing_total
21        400
22    end
23end
24
25# メソッドの実行
26exam = Exam.new([70,90,70,80,90])
27result = exam.passed_total?
28
29# インスタンスメソッドの実行結果を出力
30puts(result)
31
32# => 合格

「Exam」クラス内に合計点数と合格ラインを超えているかのインスタンスメソッドを定義しています。 定義したインスタンスメソッド「passed_total?」から、「self.class」にドット(.)でクラスメソッド名の「passing_total」を記述することにより、インスタンスメソッド内でクラスメソッドを呼び出しています。

Rubyのクラスメソッドでローカル変数を参照するパターン

Rubyのクラスメソッドでローカル変数を参照するパターンです。

1# メソッドの定義
2class Exam
3    # インスタンスの初期化
4    def initialize(scores)
5        @scores = scores
6    end
7    # 合計点数
8    def total_score
9        @scores.sum
10    end
11    # 合格点を超えているかの判定
12    def passed_total?
13        if total_score >= self.class.passing_total
14            "合格"
15        else
16            "不合格"
17        end
18    end
19    # 合計の合格ライン
20    def self.passing_total
21        400
22    end
23    # 合計の合格ラインを変更することができるようにする
24    def self.set_passing_total(score)
25        define_singleton_method(:passing_total) do
26            score
27        end
28    end
29end
30
31# メソッドの実行
32Exam.set_passing_total(450)
33exam = Exam.new([70,90,70,80,90])
34result = exam.passed_total?
35
36# インスタンスメソッドの実行結果を出力
37puts(result)
38
39# => 不合格

「define_singleton_method」を使うことで、定義時のローカル変数を特異メソッドから参照することができます。 Rubyのブロックはクロージャなので、define_singleton_method に渡したブロック内では、定義時のスコープが引き継がれており、「score」を参照できます。

おわりに

Rubyのクラスメソッドの使い方を解説してきました。 クラスメソッドとインスタンスメソッドの違いがわかれば、クラスメソッドとインスタンスメソッドの使い分けもしやすくなります。 最初は難しいかもしれませんが、しっかりと静的なクラスメソッド、動的なインスタンスメソッドを使いこなしていきましょう。 ド

【Ruby】クラスメソッドの書き方と使い方の基本 | いっしー@Webエンジニア