Ruby

【Ruby基礎】@の数だけじゃない!クラス変数とインスタンス変数の違いについてまとめてみた!

Ruby

 

今回はクラス変数とインスタンス変数の違いについてまとめてみました。

クラスとインスタンス、クラスメソッドとインスタンスメソッドなど似たような用語がたくさん出てきていますが、1つ1つ順番に理解していきましょう。

例題

以下のようなコードを設定しました。

具体的には、Reviewクラスにインスタンスメソッド(write_reviewとshow_review)を2つ定義しています。

class Review
  def write_review
    puts "タイトルを入力してください"
    title = gets.chomp
    puts "ジャンルを入力してください"
    genre = gets.chomp
    puts "感想を入力してください"
    impression = gets.chomp
  end

  def show_review
    line = "----------------"
    puts "ジャンル : #{genre}\n#{line}\n"
    puts "タイトル : #{title}\n#{line}\n"
    puts "感想 :\n#{impression}\n#{line}\n"
  end
end
よし
よし
\n(バックスラッシュ+n)は改行を表しているよ!

 

では次に、このインスタンスメソッドを呼び出す記述を追記しましょう。

class Review
  def write_review
    puts "タイトルを入力してください"
    title = gets.chomp
    puts "ジャンルを入力してください"
    genre = gets.chomp
    puts "感想を入力してください"
    impression = gets.chomp
  end

  def show_review
    line = "----------------"
    puts "ジャンル : #{genre}\n#{line}\n"
    puts "タイトル : #{title}\n#{line}\n"
    puts "感想 :\n#{impression}\n#{line}\n"
  end
end

Review.new  # インスタンスの生成
review.write_review  # write_reviewの呼び出し
review.show_review  # show_reviewの呼び出し

 

するとどうでしょうか。

インスタンスメソッド

タイトル・ジャンル・感想は入力できるものの、それらの情報が表示されていませんね。

言い換えると、write_reviewメソッドの呼び出しは成功していますが、show_reviewの呼び出しに失敗していると言えます。

 

その原因は何でしょうか?

答えはスコープです。

スコープとは、メソッドの中で定義した変数はメソッドの中でしか使えず、メソッドの外で定義した変数はメソッドの中では使えないというものです。

スコープについてはこちらの記事でも解説しています。

https://techtechmedia.com/argument-ruby/

 

この問題を解決してくれるのがインスタンス変数です。

インスタンス変数

インスタンス変数とは、クラスの中のどのインスタンスメソッドでも使用可能にするものです。

言い換えると、インスタンス変数のスコープは、そのクラスの全てのインスタンスメソッドです。

定義方法

クラス内のメソッドの中で、変数名の始めに@(アットマークを1つ)をつけて定義します。

class クラス名
  def メソッド名
    @変数名 = 値  # インスタンス変数
  end
end

使用例

先ほどの例題で見ていきましょう。

class Review
  def write_review
    puts "タイトルを入力してください"
    title = gets.chomp
    puts "ジャンルを入力してください"
    genre = gets.chomp
    puts "感想を入力してください"
    impression = gets.chomp
  end

  def show_review
    line = "----------------"
    puts "ジャンル : #{genre}\n#{line}\n"
    puts "タイトル : #{title}\n#{line}\n"
    puts "感想 :\n#{impression}\n#{line}\n"
  end
end

Review.new  # インスタンスの生成
review.write_review  # write_reviewの呼び出し
review.show_review  # show_reviewの呼び出し

 

このままだと、インスタンスメソッド(write_review)で入力された情報はスコープの範囲外のため、別のインスタンスメソッド(show_review)に渡すことができません。

そこで、以下のようにインスタンス変数を定義しましょう。

class Review
  def write_review
    puts "タイトルを入力してください"
    @title = gets.chomp
    puts "ジャンルを入力してください"
    @genre = gets.chomp
    puts "感想を入力してください"
    @impression = gets.chomp
  end

  def show_review
    line = "----------------"
    puts "ジャンル : #{@genre}\n#{line}\n"
    puts "タイトル : #{@title}\n#{line}\n"
    puts "感想 :\n#{@impression}\n#{line}\n"
  end
end

Review.new  # インスタンスの生成
review.write_review  # write_reviewの呼び出し
review.show_review  # show_reviewの呼び出し

 

こうすることで、2つのインスタンスメソッド(write_reviewとshow_review)の結果が出力されましたね。

よし
よし
インスタンスメソッド間のやり取りは、@が必要だと覚えておこう!

クラス変数

クラス変数とは、クラス全体で使用できる変数です。

クラス内であればどこでも使えるので、クラスメソッド・インスタンスメソッドの両方でも使うことができます。

定義方法

クラス変数は、変数名の始めに@@(アットマークを2つ)をつけて定義します。

class クラス名
  @@変数名 = 値
end

使用例

それでは、例を見ていきましょう。

今回はレビュー数を返す「get_review_countメソッド」を定義します。

よし
よし
クラスメソッドの定義には「self.」が必要だったね!

 

class Review
  @@review_count = 0

  def self.get_review_count
    return @@review_count
  end

  def write_review
    puts "タイトルを入力してください"
    @title = gets.chomp
    puts "ジャンルを入力してください"
    @genre = gets.chomp
    puts "感想を入力してください"
    @impression = gets.chomp
    @@review_count = @@review_count + 1
  end

  def show_review
    line = "---------------------------"
    puts "ジャンル : #{@genre}\n#{line}\n"
    puts "タイトル : #{@title}\n#{line}\n"
    puts "感想 :\n#{@impression}\n#{line}\n"
  end
end

review = Review.new  # Reviewクラスのインスタンスを生成
review.write_review  # write_reviewメソッドを実行
review.show_review  # show_reviewメソッドを実行

puts Review.get_review_count

 

このように記述することによって、レビューを追加すると、最終行(puts Review.get_review_count)でレビュー数が表示されるようになります。

今回の記述では、レビュー数は0から1にしか変わりません。

 

 

今回はクラス変数とインスタンス変数の違いについてまとめました。

この違いを理解するには、スコープという概念がしっかり頭に入っていないと難しいので、ピンと来ていない場合はスコープから学習し直しましょう!