【Ruby】レッスン5-04:クラス変数とクラスメソッドを理解しよう

一つ前のページではアクセスメソッドについて学習しました。
今回は クラス変数とクラスメソッド について見ていきましょう。
Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:メソッド編
Lesson4:コレクション編
Lesson5:オブジェクト指向編
・Lesson5-1:クラスの基本を理解しよう
・Lesson5-2:イニシャライザを理解しよう
・Lesson5-3:アクセスメソッドを理解しよう
・Lesson5-4:クラス変数とクラスメソッドを理解しよう ◁今回はココ
・Lesson5-5:privateメソッドを理解しよう
・Lesson5-6:正規表現を理解しよう
・Lesson5-7:クラスの継承を理解しよう
・Lesson5-8:ファイル操作を理解しよう
・Lesson5-9:オーバーライドを理解しよう
・Lesson5-10:モジュールを使ってみよう
・Lesson5-11:ミックスインを使ってみよう
・確認問題5-☆1:モンスター捕獲ゲームを作ろう
・確認問題5-☆2:モンスターとの戦闘ゲームを作ろう
・確認問題5-☆3:マルバツゲームを作ろう
クラス変数とクラスメソッドの基本概念を学ぼう

Rubyのオブジェクト指向プログラミングでは、「クラス変数」と「クラスメソッド」を使用することでクラス全体で共有されるデータや機能を扱うことができます。
これにより複数のインスタンスで共通の情報を管理することが可能になります。
クラス変数の定義と特徴
クラス変数はクラス全体で共有される変数であり、クラス内のすべてのインスタンスが共通してアクセス可能なデータを保存するために使用します。
クラス変数は@@
から始まる記法で定義します。
特徴
- クラス全体で共有されるため、どのインスタンスからでも同じ値にアクセスできる。
- クラスそのものやその子クラスからも参照可能。
※子クラスについてはLesson5-7で学習予定
使用例
以下のコードは、クラス変数を使用して全インスタンスで共通するカウントを管理する例です。
class User @@user_count = 0 # クラス変数の定義 def initialize(name) # イニシャライザの定義 @name = name # インスタンス変数@nameに引数nameを代入 @@user_count += 1 # クラス変数に1を加算 end def self.user_count # self.user_countメソッド(クラスメソッド)の定義 @@user_count # このメソッドの戻り値としてクラス変数を設定 end end # インスタンスを生成 user1 = User.new("Alice") # インスタンス生成 user2 = User.new("Bob") # インスタンス生成 puts User.user_count # インスタンスが2回生成された後なので、出力は2
この例では@@user_count
がクラス全体で共有され、インスタンスが作成されるたびにカウントが増加します。
クラスメソッドについては以下で説明します。
クラスメソッドの使い方と利点
クラスメソッドはクラス自身に紐づくメソッドで、インスタンスを作成しなくても呼び出すことができます。
クラスメソッドはself.
を先頭に付けて定義します。
特徴
- インスタンスメソッドとは異なり、クラスに対して直接操作を行うために使用される。
- クラス変数やクラス全体の設定を変更する際に便利。
使用例
以下のコードでは、クラスメソッドを使用してクラス変数を管理します。
class User @@user_count = 0 # クラス変数の定義 def initialize(name) @name = name # インスタンス変数の初期化 @@user_count += 1 end def self.get_user_count # クラスメソッドget_user_countの定義 "現在のユーザー数: #{@@user_count}" end end # クラスメソッドの呼び出し puts User.get_user_count # Userクラスのget_user_countメソッドの呼び出し user1 = User.new("Alice") # インスタンス生成 puts User.get_user_count # Userクラスのget_user_countメソッドの呼び出し # クラスメソッドは、クラス名を使用して呼び出す(self.を付けないよう注意)
クラス変数とクラスメソッドを使った実例
クラス変数とクラスメソッドを組み合わせると、より実践的な機能を実現できます。
例えば商品の在庫を管理する簡単なシステムを以下のように作成できます。
class Inventory @@items = {} # クラス変数としてハッシュを定義 def self.add_item(name, quantity) # クラスメソッド: アイテムを追加または在庫を更新 if @@items[name] @@items[name] += quantity # 既存のアイテムがあれば在庫を追加 else @@items[name] = quantity # 新しいアイテムであれば在庫を設定 end end def self.get_items # クラスメソッド: 現在の在庫リストを返す @@items end end # クラスメソッドを使用して在庫を管理 Inventory.add_item("りんご", 10) # "りんご"を10個追加 Inventory.add_item("バナナ", 20) # "バナナ"を20個追加 Inventory.add_item("りんご", 5) # 既存の"りんご"に5個追加(合計15個) puts Inventory.get_items # 現在の在庫リストを出力: {"りんご"=>15, "バナナ"=>20}
この例では、在庫管理システムをクラスメソッドとクラス変数で効率的に実現しています。
クラス共有機能のまとめと応用ヒント
クラス変数とクラスメソッドは、Rubyのクラス全体で共通のデータや機能を管理する強力な手段です。
これらを使いこなすことでクラス設計をシンプルかつ効率的に行えるようになります。
練習問題|貸出管理プログラムでクラス共有の使い方を学ぼう

クラス変数とクラスメソッドをしっかりと身に着けるため、練習問題に挑戦しましょう。
貸出処理を通じてクラスの役割を理解しよう
図書館の本の貸し出し管理を行うプログラムを作成しましょう。
プログラムでは以下の機能を持つクラス Library
を定義し、本の貸し出し状況を記録したり確認したりすることができるようにします。
貸し出し中の本の情報はクラス変数に保存し、クラスメソッドを通じて操作しましょう。
以下の要件に従ってコードを完成させてください。
- クラス変数
@@borrowed_books
を定義し、本のタイトルと借りた人を保存すること。 - 本を貸し出すクラスメソッド
borrow_book(title, person)
を作成すること。- 本がすでに貸し出されている場合、その旨を表示すること。
- まだ貸し出されていない場合、本のタイトルと借りた人を
@@borrowed_books
に追加し、その情報を表示すること。
- 現在貸し出し中の本を一覧表示するクラスメソッド
show_borrowed_books
を作成すること。- 貸し出し中の本がない場合、その旨を表示すること。
- 本を返却するクラスメソッド
return_book(title)
を作成すること。- 返却された本を
@@borrowed_books
から削除し、その旨を表示すること。 - 返却する本が貸し出されていない場合、その旨を表示すること。
- 返却された本を
ただし、以下のような実行結果となること。
本 'Ruby入門' を 田中 さんに貸し出しました。 本 'Python基礎' を 佐藤 さんに貸し出しました。 本 'Ruby入門' はすでに貸し出されています。 貸し出し中の本一覧: Ruby入門: 田中 さん Python基礎: 佐藤 さん 本 'Ruby入門' が返却されました。 本 'Java入門' は貸し出されていません。 貸し出し中の本一覧: Python基礎: 佐藤 さん
【ヒント】自力で解くのが難しい人へ
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント1【コードの構成を見る】
-
正解のコードは上から順に以下のような構成となっています。
1:クラス
Library
の定義
□ クラス変数@@borrowed_books
をハッシュとして初期化
2:クラスメソッドborrow_book
の定義
□@@borrowed_books
にtitle
が存在するかを確認
□ □ 真の場合、"本 '#{title}' はすでに貸し出されています。"
を出力
□ □ 偽の場合、@@borrowed_books
にtitle
をキー、person
を値として追加
□ □"本 '#{title}' を #{person} さんに貸し出しました。"
を出力
3:クラスメソッドshow_borrowed_books
の定義
□@@borrowed_books
が空かどうかを確認
□ □ 真の場合、"現在、貸し出し中の本はありません。"
を出力
□ □ 偽の場合、"貸し出し中の本一覧:"
を出力
□ □@@borrowed_books
を反復処理し、各本のタイトルと借りた人を出力
4:クラスメソッドreturn_book
の定義
□@@borrowed_books
にtitle
が存在するかを確認
□ □ 真の場合、@@borrowed_books
からtitle
を削除
□ □"本 '#{title}' が返却されました。"
を出力
□ □ 偽の場合、"本 '#{title}' は貸し出されていません。"
を出力
5:クラスメソッドborrow_book
を呼び出し、本"Ruby入門"
を"田中"
さんに貸し出す
6:クラスメソッドborrow_book
を呼び出し、本"Python基礎"
を"佐藤"
さんに貸し出す
7:クラスメソッドborrow_book
を呼び出し、既に貸し出されている本"Ruby入門"
を"鈴木"
さんに貸し出そうとする
8:クラスメソッドshow_borrowed_books
を呼び出し、貸し出し中の本一覧を表示
9:クラスメソッドreturn_book
を呼び出し、本"Ruby入門"
を返却
10:クラスメソッドreturn_book
を呼び出し、貸し出されていない本"Java入門"
を返却しようとする
11:クラスメソッドshow_borrowed_books
を呼び出し、貸し出し中の本一覧を再表示
- ヒント2【穴埋め問題にする】
-
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
class Library # クラス変数:貸し出し中の本のリスト =begin 【穴埋め問題1】 ここで貸し出し中の本の情報を保存するためのクラス変数 @@borrowed_books をハッシュとして初期化するコードを書いてください。 =end # クラスメソッド:本を貸し出す def self.borrow_book(title, person) =begin 【穴埋め問題2】 ここで貸し出し中の本の情報を確認し、貸し出し可能かどうかを判定するコードを書いてください。 =end end # クラスメソッド:貸し出し状況を表示する def self.show_borrowed_books =begin 【穴埋め問題3】 ここで貸し出し中の本のリストを出力するコードを書いてください。 貸し出し中の本がない場合は、「現在、貸し出し中の本はありません。」と出力してください。 =end end # クラスメソッド:本を返却する def self.return_book(title) =begin 【穴埋め問題4】 ここで指定された本を返却し、クラス変数 @@borrowed_books から削除するコードを書いてください。 =end end end # 動作確認コード Library.borrow_book("Ruby入門", "田中") Library.borrow_book("Python基礎", "佐藤") Library.borrow_book("Ruby入門", "鈴木") # 重複チェック Library.show_borrowed_books Library.return_book("Ruby入門") Library.return_book("Java入門") # 存在しない本の返却 Library.show_borrowed_books
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
この問題の解答例と解説
この問題の正解コードとその解説は以下の通りです。
クリックして開いて確認してください。
- 正解コード
-
class Library # クラス変数:貸し出し中の本のリスト @@borrowed_books = {} # クラスメソッド:本を貸し出す # 本のタイトル(title)と借りた人(person)を登録 def self.borrow_book(title, person) if @@borrowed_books[title] puts "本 '#{title}' はすでに貸し出されています。" else @@borrowed_books[title] = person puts "本 '#{title}' を #{person} さんに貸し出しました。" end end # クラスメソッド:貸し出し状況を表示する def self.show_borrowed_books if @@borrowed_books.empty? puts "現在、貸し出し中の本はありません。" else puts "貸し出し中の本一覧:" @@borrowed_books.each do |title, person| puts "#{title}: #{person} さん" end end end # クラスメソッド:本を返却する def self.return_book(title) if @@borrowed_books[title] @@borrowed_books.delete(title) puts "本 '#{title}' が返却されました。" else puts "本 '#{title}' は貸し出されていません。" end end end # 動作確認コード Library.borrow_book("Ruby入門", "田中") Library.borrow_book("Python基礎", "佐藤") Library.borrow_book("Ruby入門", "鈴木") # 重複チェック Library.show_borrowed_books Library.return_book("Ruby入門") Library.return_book("Java入門") # 存在しない本の返却 Library.show_borrowed_books
- 正解コードの解説
-
コードをブロックごとに分割して解説します。
クラスの定義とクラス変数
class Library @@borrowed_books = {}
class Library
:Library
という名前のクラスを定義しています。
クラスはオブジェクト指向プログラミングの基本的な構造で、データや動作をまとめることができます。@@borrowed_books
:クラス変数として定義されています。
クラス変数はクラス全体で共有されるためどのメソッドからもアクセスできます。
このプログラムでは、貸し出し中の本の情報を管理するために使用します。
本を貸し出すメソッド
def self.borrow_book(title, person) if @@borrowed_books[title] puts "本 '#{title}' はすでに貸し出されています。" else @@borrowed_books[title] = person puts "本 '#{title}' を #{person} さんに貸し出しました。" end end
def self.borrow_book
:クラスメソッドの定義です。クラスメソッドはLibrary.borrow_book
のようにクラスから直接呼び出すことができます。if @@borrowed_books[title]
:貸し出し中の本がすでにリストに存在するかを確認します。@@borrowed_books[title] = person
:新しい貸し出し情報をクラス変数に登録します。puts
:操作の結果をコンソールに表示します。
貸し出し状況を表示するメソッド
def self.show_borrowed_books if @@borrowed_books.empty? puts "現在、貸し出し中の本はありません。" else puts "貸し出し中の本一覧:" @@borrowed_books.each do |title, person| puts "#{title}: #{person} さん" end end end
if @@borrowed_books.empty?
:貸し出し中の本がない場合の処理を実行します。@@borrowed_books.each
:ハッシュのデータを反復処理して、各本のタイトルと借りた人を出力します。
本を返却するメソッド
def self.return_book(title) if @@borrowed_books[title] @@borrowed_books.delete(title) puts "本 '#{title}' が返却されました。" else puts "本 '#{title}' は貸し出されていません。" end end
@@borrowed_books.delete(title)
:指定されたタイトルの本をリストから削除します。puts
:返却処理の結果を表示します。
動作確認コード
Library.borrow_book("Ruby入門", "田中") Library.borrow_book("Python基礎", "佐藤") Library.borrow_book("Ruby入門", "鈴木") Library.show_borrowed_books Library.return_book("Ruby入門") Library.return_book("Java入門") Library.show_borrowed_books
この部分はクラスメソッドを実行して、プログラムの動作を確認しています。
まとめ
このコードではクラス変数とクラスメソッドを使ったデータ管理の基本を学びました。
クラス変数を利用することでクラス全体で共有される情報を簡単に管理できます。またクラスメソッドはそのクラスに直接関係する操作を実現するために便利です。
このコードを通じてRubyにおけるオブジェクト指向プログラミングの基礎を理解し、今後の応用に役立ててください!
FAQ|Rubyのクラス変数とクラスメソッドの使い方
- Q1. Rubyでクラス変数を使うときに注意すべき点は何ですか?
-
クラス変数(@@)はすべてのインスタンス間で共有されるため、意図せず他のオブジェクトに影響を与える可能性があります。多くのインスタンスから同時に変更が行われる場面では、状態管理が複雑になりやすいため、用途を限定して使うのが安全です。
- Q2. クラスメソッドはどんなときに使うのが適切ですか?
-
クラスメソッドは、インスタンスを生成せずにクラス全体に関連する情報を操作・取得したいときに有効です。たとえば、在庫の集計やユーザー数のカウントなど、インスタンスに依存しない処理に適しています。
- Q3. クラス変数と定数(CONST)の違いは何ですか?
-
クラス変数(@@)は変更可能で、実行中に値を更新できますが、定数(CONST)は原則として変更不可で、一度代入したら変更しない前提で使われます。どちらもクラス全体で共有されますが、用途と性質が異なります。