目次
開発環境
- 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 2 3 4 5 6 7 8 9 10 11 12 | # クラスの定義 class SampelClass # クラスメソッドの定義 def self.sample_class_method puts "クラスメソッドを実行します。" end end # クラスメソッドの呼び出し SampelClass.sample_class_method # =>クラスメソッドを実行します。 |
上記の例では、「sample_class_method」は「SampelClass」のクラスメソッドです。
クラスメソッドは、クラス自体に関連付けられているため、インスタンスを作成する必要はありません。
クラス定義内に「class << self ブロック」を使用する
クラス定義内に「class << self ブロック」を使用する書き方です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # クラスの定義 class SampelClass class << self # クラスメソッドの定義 def sample_class_method puts "クラスメソッドを実行します。" end end end # クラスメソッドの呼び出し SampelClass.sample_class_method # =>クラスメソッドを実行します。 |
ネストは一つ深くなりますが、「class << self」内でクラスメソッドを定義することにより、ブロック内のメソッドはクラスメソッドとして定義することができます。
Rubyのクラスメソッドの使い方
Rubyのクラスメソッドのよくあるパターンをサンプルコードを用いて使い方の解説をしていきます。
Rubyのクラスメソッドをクラスオブジェクトから実行するパターン
Rubyのクラスメソッドをクラスオブジェクトから実行するパターンです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # メソッドの定義 class Exam # 合計の合格ライン def self.passing_total 400 end end # クラスメソッドの実行 passing_total = Exam.passing_total # インスタンスメソッドの実行結果を出力 puts(passing_total) # => 400 |
「Exam」クラスを定義してテストの合格点をクラスメソッドで定義をしています。
サンプルコードでは「Exam」クラスにドット(.)で「passing_total」を記述してクラスメソッドを呼び出し、合計の合格ラインを出力しています。
Rubyのクラスメソッドをインスタンスメソッドから実行するパターン
Rubyのクラスメソッドをインスタンスメソッドから実行するパターンです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # メソッドの定義 class Exam # インスタンスの初期化 def initialize(scores) @scores = scores end # 合計点数 def total_score @scores.sum end # 合格点を超えているかの判定 def passed_total? if total_score >= self.class.passing_total "合格" else "不合格" end end # 合計の合格ライン def self.passing_total 400 end end # メソッドの実行 exam = Exam.new([70,90,70,80,90]) result = exam.passed_total? # インスタンスメソッドの実行結果を出力 puts(result) # => 合格 |
「Exam」クラス内に合計点数と合格ラインを超えているかのインスタンスメソッドを定義しています。
定義したインスタンスメソッド「passed_total?」から、「self.class」にドット(.)でクラスメソッド名の「passing_total」を記述することにより、インスタンスメソッド内でクラスメソッドを呼び出しています。
Rubyのクラスメソッドでローカル変数を参照するパターン
Rubyのクラスメソッドでローカル変数を参照するパターンです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # メソッドの定義 class Exam # インスタンスの初期化 def initialize(scores) @scores = scores end # 合計点数 def total_score @scores.sum end # 合格点を超えているかの判定 def passed_total? if total_score >= self.class.passing_total "合格" else "不合格" end end # 合計の合格ライン def self.passing_total 400 end # 合計の合格ラインを変更することができるようにする def self.set_passing_total(score) define_singleton_method(:passing_total) do score end end end # メソッドの実行 Exam.set_passing_total(450) exam = Exam.new([70,90,70,80,90]) result = exam.passed_total? # インスタンスメソッドの実行結果を出力 puts(result) # => 不合格 |
「define_singleton_method」を使うことで、定義時のローカル変数を特異メソッドから参照することができます。
Rubyのブロックはクロージャなので、define_singleton_method に渡したブロック内では、定義時のスコープが引き継がれており、「score」を参照できます。
おわりに
Rubyのクラスメソッドの使い方を解説してきました。
クラスメソッドとインスタンスメソッドの違いがわかれば、クラスメソッドとインスタンスメソッドの使い分けもしやすくなります。
最初は難しいかもしれませんが、しっかりと静的なクラスメソッド、動的なインスタンスメソッドを使いこなしていきましょう。
ド