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.Studentクラスの定義
1-1. attr_accessor
でname
とscores
のアクセサメソッドを定義
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
を呼び出し、クラス全体の平均点を計算し出力
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
# 学生クラスを定義します 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
は、クラスの中で使う属性(name
とscores
)を定義し、その属性を読み書きできるようにします。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を活用しています。
問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。