ローカル変数とインスタンス変数の違いを理解しよう
学習の目標
本章では、以下の内容を学習します。
- ローカル変数とインスタンス変数の基本的な違いを理解する
- それぞれの変数の特徴と使える範囲を学ぶ
- それぞれの変数がいつまで値を保持するかを理解する
- 実際のコードで適切に変数を使い分ける方法を身につける
はじめに
今回は、ローカル変数とインスタンス変数の違いと、それぞれの使い分けについて学んでいきます。
この2つの変数タイプは一見似ていますが、使える範囲といつまで値が残るかという点で大きく異なります。プログラミングにおいて、この違いを理解することは非常に重要です。
ファイルの準備
まずは、variable_scope.rbというファイルを作成しましょう。
VS Codeで新しいファイルを作成してください。これから、このファイルにクラスを定義していきます。
ローカル変数の特徴
ローカル変数の基本
ローカル変数は、その変数が定義されたメソッドやブロックの中だけで使える変数です。メソッドの処理が終わると、その中で定義したローカル変数は消えてしまいます。これは一時的な計算結果を保持するのに適しています。
class Calculator  def calculate_total(price)    tax = 0.1              # これはローカル変数    total = price * (1 + tax)    puts "税込金額:#{total}円"  end
  def show_tax    puts "消費税:#{tax}"  # エラーになります  endend
calc = Calculator.newcalc.calculate_total(1000)  # 税込金額:1100円と表示されるcalc.show_tax              # エラー:taxが未定義このコードを実行すると、show_taxメソッドでtax変数にアクセスしようとした時点でエラーが発生します。なぜなら、ローカル変数taxはcalculate_totalメソッドの中でしか使えないからです。
ローカル変数の命名規則
ローカル変数は必ず小文字またはアンダースコア(_)で始める必要があります。これはRubyの命名規則であり、Rubyはこの規則によって変数の種類を判別しています。
例えば、以下のような命名が可能です。
- name
- first_name
- _temporary_value
ローカル変数の使える範囲
ローカル変数の使える範囲は、その変数が定義されたブロックやメソッド内に限定されます。別のメソッドや外部からはアクセスできません。
def method_a  local_var = "メソッドAの中の変数"  puts local_var  # 正常に表示されるend
def method_b  puts local_var  # エラー:local_varは定義されていないend
method_amethod_b  # エラーが発生インスタンス変数の特徴
インスタンス変数の基本
インスタンス変数は、インスタンスが持つデータを保持するための変数です。クラスの中のどのメソッドからでも使えるという特徴があります。
class Calculator  def calculate_total(price)    @tax = 0.1               # これはインスタンス変数    total = price * (1 + @tax)    puts "税込金額:#{total}円"  end
  def show_tax    puts "消費税:#{@tax}"   # @taxを参照できます  endend
calc = Calculator.newcalc.calculate_total(1000)   # 税込金額:1100円と表示されるcalc.show_tax               # 消費税:0.1と表示されるこのコードでは、インスタンス変数@taxをcalculate_totalメソッドで設定し、別のshow_taxメソッドでも参照しています。これが可能なのは、インスタンス変数がインスタンス全体で共有されているためです。
インスタンス変数の命名規則
インスタンス変数は必ず@(アットマーク)で始まります。これがインスタンス変数の目印となり、Rubyは@から始まる変数をインスタンス変数として認識します。
例えば、以下のような命名が可能です。
- @name
- @first_name
- @age
インスタンス変数の使える範囲
インスタンス変数の使える範囲はそのインスタンス内全体です。つまり、そのインスタンスのどのメソッドからも同じインスタンス変数にアクセスできます。ただし、別のインスタンスからは直接アクセスできません。各インスタンスは自分自身のインスタンス変数のセットを持っています。
class Person  def set_name(name)    @name = name  end
  def greet    puts "こんにちは、#{@name}さん"  # どのメソッドからでも@nameにアクセス可能  endend
person1 = Person.newperson1.set_name("田中")person1.greet  # こんにちは、田中さん
person2 = Person.newperson2.set_name("佐藤")person2.greet  # こんにちは、佐藤さん
# person1と person2は別々の@name変数を持っています値がいつまで残るかの違い
ローカル変数の値の保持期間
ローカル変数とインスタンス変数では、値がいつまで残るかも大きく異なります。
ローカル変数は、メソッドの呼び出しごとに新しく作られ、メソッドの終了とともに消えます。つまり、メソッドが終了すると、その中で定義されたローカル変数は値を失い、次にメソッドが呼び出されると再び初期化されます。
インスタンス変数の値の保持期間
一方、インスタンス変数は、そのインスタンスが存在する限り値を保持し続けます。メソッドの呼び出しが終わっても値は消えません。
class Counter  def count_up    count = 0          # ローカル変数    @number = 0 if @number.nil?  # インスタンス変数(初回のみ0で初期化)
    count += 1    @number += 1
    puts "count: #{count}"    puts "number: #{@number}"  endend
counter = Counter.newcounter.count_up    # count: 1, number: 1と表示(両方とも最初は0から)counter.count_up    # count: 1, number: 2と表示(countは毎回リセット、numberは値を保持)counter.count_up    # count: 1, number: 3と表示このコードを実行すると、ローカル変数countは毎回1になりますが、インスタンス変数@numberは呼び出すたびに増えていきます。これは、ローカル変数がメソッドの呼び出しごとにリセットされるのに対し、インスタンス変数はインスタンスが存在する限り値を保持し続けるためです。
使い分けの基準
基本的な使い分け
では、ローカル変数とインスタンス変数をどのように使い分ければよいのでしょうか。
基本的には、以下のように覚えておくと良いでしょう。
- ローカル変数:メソッド内だけで完結する一時的な計算に使う
- インスタンス変数:インスタンスの状態として保持しておきたい情報に使う
使い分けの実践例
実際のコードで見てみましょう。
class User  def format_name(first, last)    # メソッド内だけで使う一時的な変数はローカル変数で十分    full_name = "#{last} #{first}"    # ここではローカル変数    puts full_name  end
  def set_age(age)    # インスタンスが存在する間、値を保持したい場合はインスタンス変数    @age = age    # 年齢は後からでも使いたいのでインスタンス変数  end
  def show_age    puts "年齢:#{@age}歳"   # 別のメソッドでも@ageを参照できる  end
  def adult?    # @ageの値を使って判定    @age >= 20    # インスタンス変数は他のメソッドでも使える  endend
user = User.newuser.set_age(25)user.show_age    # 25歳と表示puts user.adult? # trueと表示この例では、format_nameメソッド内で使うfull_nameはメソッド内だけで使われる一時的な変数なので、ローカル変数として定義しています。
一方、@ageはユーザーの年齢を表す重要な情報で、set_age、show_age、adult?など複数のメソッドで使用するため、インスタンス変数として定義しています。
複数メソッド間での値の共有
インスタンス変数の主な利点は、複数のメソッド間で値を共有できることです。以下の例を見てみましょう。
class ShoppingCart  def initialize    @items = []  # 買い物カゴの中身を保持するインスタンス変数  end
  def add_item(item)    @items.push(item)    puts "#{item}を買い物カゴに入れました"  end
  def show_items    puts "買い物カゴの中身:"    @items.each { |item| puts "- #{item}" }  end
  def total_items    @items.length  endend
cart = ShoppingCart.newcart.add_item("りんご")cart.add_item("バナナ")cart.show_itemsputs "合計#{cart.total_items}個の商品があります"この例では、買い物カゴの中身を表す@itemsをインスタンス変数として定義しています。これにより、add_item、show_items、total_itemsの各メソッドで買い物カゴの情報を共有できます。
もしこれをローカル変数で実装しようとすると、メソッド間でデータを受け渡す必要があり、コードが複雑になってしまいます。
まとめ
今回は、ローカル変数とインスタンス変数の違いについて学びました。
ローカル変数は、定義されたメソッドの中だけで使える一時的な変数です。メソッドが終了すると値は消えます。メソッド内の一時的な計算や処理に適しています。
インスタンス変数は、インスタンスが存在する間ずっと値を保持し、クラスのどのメソッドからでも使えます。インスタンスの状態や性質を表すデータを保持するのに適しています。
一時的な処理にはローカル変数を、インスタンスの状態を表すデータにはインスタンス変数を使うのが基本です。
変数の種類を適切に使い分けることで、より読みやすく、メンテナンスしやすいプログラムを書くことができます。それぞれの特性を理解し、状況に応じて最適な変数タイプを選択しましょう。
Starterプランでより詳しく学習
この先のコンテンツを読むにはStarterプラン以上が必要です。より詳細な解説、実践的なサンプルコード、演習問題にアクセスして学習を深めましょう。