Rubyでクラスを作成してオブジェクト指向プログラミングを行う際、必ずと言っていいほど登場するのが「インスタンス変数」です。
@name や @price のように、変数の前にアットマーク(@)が付いているのが特徴ですが、ローカル変数やクラス変数と何が違うのか、正確に理解できていない方もいるでしょう。
「クラスから作ったオブジェクトごとに別々のデータを持たせたい」
こうした要望を実現するために不可欠なのがインスタンス変数です。
この記事では、Rubyにおけるインスタンス変数の基本的な使い方から、外部からアクセスするためのアクセサメソッド(attr_accessor)、そして間違いやすいクラス変数との違いまで、最新情報を踏まえて解説します。
![]() 執筆者:マヒロ |
|
インスタンス変数とは?ローカル変数との違い
インスタンス変数とは、クラスから生成されたインスタンス(オブジェクト)ごとに個別に保持される変数のことです。
変数名の先頭に @(アットマーク)を付けることで定義されます。
ローカル変数との決定的な違い
Rubyのメソッド内で定義される通常の変数(ローカル変数)は、そのメソッドの中でしか使えません。
メソッドの処理が終わると消滅してしまいます。
一方、インスタンス変数は、同じインスタンス内であれば、どのメソッドからでも参照・変更が可能です。
また、インスタンスが存在する限り、値は保持され続けます。
基本的な書き方
class User
def initialize(name)
# インスタンス変数の定義と代入
@name = name
end
def introduce
# 別のメソッドからでも参照できる
puts "私の名前は#{@name}です。"
end
end
# インスタンス化
user1 = User.new("Tanaka")
user1.introduce
user2 = User.new("Suzuki")
user2.introduce
実行結果
私の名前はTanakaです。
私の名前はSuzukiです。
User クラスの initialize メソッドで @name に値を代入しています。
その後、introduce メソッド内で @name を参照していますが、問題なく値が表示されています。
これがインスタンス変数の「メソッドをまたいで値を共有できる」という特徴です。
また、user1 と user2 でそれぞれ別の名前が表示されていることから、インスタンスごとに独立したデータを持っていることがわかります。
外部からインスタンス変数にアクセスする方法
Rubyのインスタンス変数は、デフォルトではクラスの外部から直接アクセスすることができません。
例えば、以下のようなコードはエラーになります。
user = User.new("Tanaka")
# puts user.@name # 文法エラーになる
# puts user.name # メソッドが定義されていないためエラー(NoMethodError)
外部から値を読み取ったり書き込んだりするためには、専用のメソッド(アクセサメソッド)を用意する必要があります。
手動でゲッターとセッターを定義する
値を読み取るメソッドを「ゲッター(Getter)」、値を書き込むメソッドを「セッター(Setter)」と呼びます。
class Item
def initialize(price)
@price = price
end
# ゲッター(値を取得する)
def price
@price
end
# セッター(値を変更する)
def price=(new_price)
@price = new_price
end
end
item = Item.new(100)
puts item.price # ゲッター呼び出し => 100
item.price = 200 # セッター呼び出し
puts item.price # => 200
attr_accessor で簡単に定義する【推奨】
すべての変数に対してゲッターとセッターを手動で書くのは大変です。
Rubyにはこれらを自動的に定義してくれる便利なメソッドが用意されています。
attr_accessor: 読み取り(get)と書き込み(set)の両方を定義attr_reader: 読み取り(get)のみ定義attr_writer: 書き込み(set)のみ定義
class Item
# これだけで @name と @price のゲッター・セッターが作られる
attr_accessor :name, :price
def initialize(name, price)
@name = name
@price = price
end
end
item = Item.new("Apple", 150)
puts item.name # => Apple
item.price = 200
puts item.price # => 200
実務では、この attr_accessor などを活用してコードを簡潔に保つのが一般的です。
インスタンス変数のスコープと未定義時の挙動
インスタンス変数は、そのオブジェクトの中であればどこからでもアクセスできますが、注意点もあります。
未定義のインスタンス変数は nil になる
ローカル変数の場合、定義していない変数を使おうとするとエラー(NameError)になりますが、インスタンス変数は未定義の場合 nil を返します。
エラーにはなりません。
class Sample
def check
# @data はどこにも定義されていない
p @data
end
end
obj = Sample.new
obj.check
実行結果
nil
これはバグの原因になりやすいポイントです。
「値が入っているはずなのに nil になっている」という場合は、スペルミスや初期化漏れを疑いましょう。
インスタンス変数とクラス変数の違い
@ ひとつのインスタンス変数に対し、@@ ふたつの変数を「クラス変数」と呼びます。 この2つはスコープ(有効範囲)が大きく異なります。
- インスタンス変数 (
@name): インスタンス(個体)ごとに別々の値を持つ。 - クラス変数 (
@@count): そのクラスのすべてのインスタンスで一つの値を共有する。
class Counter
# クラス変数(共有される)
@@count = 0
def initialize
@@count += 1
# インスタンス変数(個別に持つ)
@my_number = @@count
end
def show
puts "私は #{@my_number} 番目のインスタンスです。総数は #{@@count} です。"
end
end
a = Counter.new
b = Counter.new
c = Counter.new
a.show
b.show
c.show
実行結果
私は 1 番目のインスタンスです。総数は 3 です。
私は 2 番目のインスタンスです。総数は 3 です。
私は 3 番目のインスタンスです。総数は 3 です。
@my_number はインスタンスが生成された時点の番号を個別に記憶していますが、@@count はすべてのインスタンスで共有されているため、最終的な総数(3)が全員に表示されています。
クラス変数は影響範囲が広く、意図しない副作用を生む可能性があるため、使用には注意が必要です。
Railsにおけるインスタンス変数の役割
Ruby on Railsにおいて、インスタンス変数はさらに特別な役割を持ちます。
コントローラー(Controller)で定義したインスタンス変数は、自動的にビュー(View)に渡され、画面表示に利用できるようになります。
# UsersController
def show
@user = User.find(params[:id])
# ここで定義した @user が、show.html.erb でそのまま使える
end
これはRailsフレームワークの仕様によるもので、Ruby自体の基本的な機能とは少し異なりますが、Rails開発者にとっては最も馴染み深い使い方の一つでしょう。
Rubyのスキルを活かして年収を上げる方法
以上、Rubyのインスタンス変数について解説してきました。
なお、Rubyのスキルがある場合には、「転職して年収をアップさせる」「副業で稼ぐ」といった方法を検討するのがおすすめです。
Rubyエンジニアの年収や単価は高い傾向にあるため、転職によって数十万円の年収アップはザラで、100万円以上年収が上がることも珍しくありません。
なお、転職によって年収を上げたい場合は、エンジニア専門の転職エージェントサービスを利用するのが最適です。
併せて、副業案件を獲得できるエージェントにも登録しておくと、空いている時間を活かして稼げるようなRubyの案件を探しやすくなります。
転職エージェントも副業エージェントも、登録・利用は完全無料なので、どんな求人や副業案件があるのか気になる方は、気軽に利用してみるとよいでしょう。



