Ruby練習問題4-3:クラスメソッドとインスタンスメソッドを理解しよう

記事内に商品プロモーションを含む場合があります

Rubyの初心者向け問題4-3:クラスメソッドとインスタンスメソッドを理解しよう

この問題を解くために必要な知識:
【レベル1~3の知識】
コメントの書き方、変数と定数、基本データ型、四則演算と演算子、入力と出力、文字列操作、分岐処理(if、if~else、elsif、case)、繰り返し処理(for、while、until、each)、範囲(Range)、例外処理(begin-rescue-end)、配列(Array)、ハッシュ(Hash)、コレクション操作(配列、ハッシュの操作)、Enumerableモジュール、メソッドの定義と呼び出し、メソッドの戻り値、クラスの定義と使用、コンストラクタ、クラスの継承、モジュールの定義と使用、ミックスイン

【レベル4の知識】
アクセスメソッド(ゲッター、セッター)、カプセル化、クラスメソッドとインスタンスメソッド、共通メソッドブロックとイテレータプロック(Proc)ラムダ(Lambda)ファイル操作(読み書き)正規表現メタプログラミングの基礎

<<前の問題 問題集Top 次の問題>>

Rubyの文法「クラスメソッドとインスタンスメソッド」とは

ここではクラスメソッドとインスタンスメソッドの意味や使い方を復習します。必要ない方はここをクリックして練習問題へ飛びましょう。



Rubyでは、メソッドには大きく分けて2種類があります。それは「クラスメソッド」と「インスタンスメソッド」です。ここでは、その違いと使い方を簡単に説明します。

インスタンスメソッドとは?

インスタンスメソッドは、クラスから生成されたインスタンス(オブジェクト)に対して使うことができるメソッドです。

クラスを設計して、そのクラスからオブジェクトを作成した後、そのオブジェクトに対して呼び出すメソッドを定義する場合がこれに該当します。

class MathFunctions
  # インスタンスメソッドの定義
  def square(x)
    x * x
  end
end

# クラスからインスタンスを作成
math = MathFunctions.new

# インスタンスメソッドを呼び出す
puts math.square(3)  # 出力: 9

この例では、MathFunctionsというクラスから作成されたmathというインスタンスを使って、squareというインスタンスメソッドを呼び出しています。

クラスメソッドとは?

クラスメソッドは、クラス自体に対して定義するメソッドです。クラスメソッドは、そのクラスのインスタンスを作成せずに、クラス名を使って直接呼び出すことができます。

class MathFunctions
  # クラスメソッドの定義
  def self.pi
    3.14159
  end
end

# クラスメソッドを呼び出す
puts MathFunctions.pi  # 出力: 3.14159

ここでは、MathFunctionsクラスのpiというクラスメソッドをインスタンスを作らずに直接呼び出しています。

クラスメソッドを定義する際には、メソッド名の前にself.を付けることでクラスメソッドになります。

まとめ

  • インスタンスメソッドは、クラスから作成されたインスタンスに対して使われます。
  • クラスメソッドは、インスタンスを作成せずにクラス自体に対して使われます。

クラスメソッドとインスタンスメソッドの違いを理解すると、クラス設計やメソッドの使い方がより明確になり、効率的にプログラミングできるようになります。




Ruby練習問題4-3_「学生の成績管理システム」を作ろう

複数の学生の平均点を計算するプログラムを作成してください。

各学生には名前と複数のテストの得点があります。インスタンスメソッドを使って個々の学生の平均点を計算し、クラスメソッドを使ってクラス全体の平均点を計算することが目標です。

この問題の要件

以下の要件に従ってコードを完成させてください。

  • Studentクラスを作成すること。
  • Studentクラスには、以下の属性を持たせること:
    • name(名前)
    • scores(得点の配列)
  • Studentクラスに以下のメソッドを実装すること:
    • インスタンスメソッドaverage_score:その学生の平均点を計算する。
    • クラスメソッドclass_average:クラス全体の平均点を計算する。
  • 学生の情報は配列に格納し、各学生の平均点とクラス全体の平均点を表示すること。

ただし、以下のような実行結果となること。

----- ↓出力される結果の例↓ -----

太郎の平均点は85.0点です。
花子の平均点は75.0点です。
次郎の平均点は85.0点です。
クラス全体の平均点は81.66666666666667点です。

----- ↑出力される結果の例↑ -----

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。

1.Studentクラスの定義
 1-1. attr_accessornamescoresのアクセサメソッドを定義
 1-2. initializeメソッドで名前と得点(scores)を初期化

2.インスタンスメソッドaverage_scoreの定義
 2-1. @scoresの合計を計算
 2-2. 得点の数で割り、平均点を返す

3.クラスメソッドclass_averageの定義
 3-1. クラス全体の合計得点を保持するためのtotal_scores変数を初期化
 3-2. 学生の人数をtotal_studentsで保持
 3-3. 各学生ごとの平均点を取得し、total_scoresに加算
 3-4. クラス全体の平均点を計算し、返す

4.Studentクラスのインスタンス作成
 4-1. students配列に各学生のインスタンスをStudent.newで作成
 4-2. 学生の名前と得点をそれぞれ初期化

5.各学生の平均点を出力
 5-1. students.eachを使い、全ての学生の平均点を順に出力

6.クラス全体の平均点を出力
 6-1. Student.class_averageを呼び出し、クラス全体の平均点を計算し出力

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

# 学生クラスを定義します
class Student
  attr_accessor :name, :scores
  
  # コンストラクタで名前と得点の配列を初期化します
  def initialize(name, scores)
    @name = name
    @scores = scores
  end
  
  # インスタンスメソッド:この学生の平均点を計算します
  def average_score
    =begin
    【穴埋め問題1】
    ここに、得点の合計を計算し、その数を得点の数で割るコードを書いてください。
    結果として得られるのは、学生の平均点です。
    =end
  end
  
  # クラスメソッド:クラス全体の平均点を計算します
  def self.class_average(students)
    =begin
    【穴埋め問題2】
    ここに、全ての学生の平均点を合計して、クラス全体の平均点を計算するコードを書いてください。
    学生の平均点を計算するためには、eachメソッドを使って全ての学生のインスタンスメソッドを呼び出す必要があります。
    =end
  end
end

# 学生の情報を初期化します
students = [
  Student.new("太郎", [80, 90, 85]),
  Student.new("花子", [70, 75, 80]),
  Student.new("次郎", [85, 80, 90])
]

# 各学生の平均点を表示します
students.each do |student|
  puts "#{student.name}の平均点は#{student.average_score}点です。"
end

# クラス全体の平均点を表示します
puts "クラス全体の平均点は#{Student.class_average(students)}点です。"

 

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。



解答例と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

********************

# 学生クラスを定義します
class Student
  attr_accessor :name, :scores
  
  # コンストラクタで名前と得点の配列を初期化します
  def initialize(name, scores)
    @name = name
    @scores = scores
  end
  
  # インスタンスメソッド:この学生の平均点を計算します
  def average_score
    # 合計点を得点の数で割って平均点を求めます
    @scores.sum / @scores.size.to_f
  end
  
  # クラスメソッド:クラス全体の平均点を計算します
  def self.class_average(students)
    total_scores = 0
    total_students = students.size
    
    students.each do |student|
      total_scores += student.average_score
    end
    
    total_scores / total_students.to_f
  end
end

# 学生の情報を初期化します
students = [
  Student.new("太郎", [80, 90, 85]),
  Student.new("花子", [70, 75, 80]),
  Student.new("次郎", [85, 80, 90])
]

# 各学生の平均点を表示します
students.each do |student|
  puts "#{student.name}の平均点は#{student.average_score}点です。"
end

# クラス全体の平均点を表示します
puts "クラス全体の平均点は#{Student.class_average(students)}点です。"

********************

コードの解説

この解説では、学生クラスを使った平均点の計算方法を初心者向けに説明します。

このプログラムでは、クラスメソッドとインスタンスメソッドという2種類のメソッドが登場します。

それぞれの役割を理解しながら、プログラム全体の動作を確認していきましょう。

クラスと属性の定義

class Student
  attr_accessor :name, :scores

まず、Studentというクラスを定義しています。

attr_accessorは、クラスの中で使う属性(namescores)を定義し、その属性を読み書きできるようにします。nameは学生の名前、scoresはテストの点数の配列を表します。

コンストラクタ

def initialize(name, scores)
  @name = name
  @scores = scores
end

initializeメソッドはコンストラクタと呼ばれ、クラスから新しいインスタンス(オブジェクト)を作成するときに呼び出されます。

ここでは、学生の名前と得点を初期化しています。

インスタンスメソッド average_score

def average_score
  @scores.sum / @scores.size.to_f
end

この部分がインスタンスメソッドです。インスタンスメソッドは、Studentクラスから作成された個々の学生に対して使われます。

このメソッドでは、scoresの合計を計算し、その数をscoresの数で割ることで、その学生の平均点を計算しています。

ポイント:インスタンスメソッドとは?

インスタンスメソッドは、クラスから生成された個々のオブジェクトに対して動作します。

つまり、太郎さんや花子さんといった個別の学生ごとに、average_scoreを計算するために使われます。

クラスメソッド class_average

def self.class_average(students)
  total_scores = 0
  students.each do |student|
    total_scores += student.average_score
  end
  total_scores / students.size.to_f
end

この部分はクラスメソッドです。クラスメソッドは、selfを使って定義され、クラス全体に対して操作を行います。

このメソッドでは、すべての学生の平均点を合計し、その結果を学生の人数で割ることで、クラス全体の平均点を計算します。

ポイント:クラスメソッドとは?

クラスメソッドは、クラス全体に対して適用されるメソッドです。インスタンスメソッドとは異なり、個々のオブジェクトではなく、クラス自体に関する操作を行います。

この例では、全学生の平均点を計算しています。

学生の情報を初期化

students = [
  Student.new("太郎", [80, 90, 85]),
  Student.new("花子", [70, 75, 80]),
  Student.new("次郎", [85, 80, 90])
]

ここでは、3人の学生(太郎、花子、次郎)の情報を設定しています。それぞれの学生は、Student.newで新しいインスタンスとして作成されます。

各学生の平均点を表示

students.each do |student|
  puts "#{student.name}の平均点は#{student.average_score}点です。"
end

この部分では、各学生のaverage_scoreインスタンスメソッドを使って、個々の学生の平均点を計算し、出力しています。

クラス全体の平均点を表示

puts "クラス全体の平均点は#{Student.class_average(students)}点です。"

最後に、クラス全体の平均点を表示するために、class_averageクラスメソッドを呼び出しています。このメソッドは、全学生の平均点をまとめて計算します。

<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

この問題を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Ruby練習問題集へ戻る
    トップページへ戻る