この記事を見てるあなたはRubyを学び始めてまだ間もないかもしれません。
Rubyには変数の種類がいくつかあり、「これは何の変数なんだっけ」となることありますよね?
でもご安心ください。
Rubyの変数について忘れてしまってもこの記事に戻ってくれば何度でも理解できます。
今まで曖昧だった変数の種類を理解することは、Rubyでのプログラミング上達には必ず必要なのでここで理解しましょう!
そもそも変数とは
変数は、プログラミングにおける基本的な要素であり、データを一時的に格納するための「容器」として機能します。
これにより、プログラムの実行中に情報を保持し、操作することが可能になります。
変数にはさまざまな種類があり、それぞれ特定の範囲や目的で使用されます。
例えば、ローカル変数、インスタンス変数、クラス変数、グローバル変数、定数などがあり、それぞれがプログラム内で異なる役割を担うのです。
Rubyでは、これらの変数の区別は、変数名の先頭に使用される特定の文字によって行われます。
変数の定義と代入
変数を使用する前は、必ず定義を行う必要があります。
変数の定義とは、変数名を割り当て、その変数がデータを保持できるように準備するプロセスのこと。
Rubyでは、「変数名 = オブジェクト」という形式で変数を定義し、オブジェクトを変数に割り当てる(代入する)ことができます。
ここでの「=」記号は、数学的な等しいという意味ではなく、「右辺のオブジェクトを左辺の変数に割り当てる」という意味で使用されます。
これにより、変数に値が「代入」され、プログラムの他の部分からその値を参照できるようになるのです。
変数を利用する
変数の最も基本的な使用法は、値の参照と変更です。
変数に値を代入した後、プログラム内でその変数名を使用すると、割り当てられたデータが参照されます。
この操作を「変数の値を参照する」と言います。
また、変数に一度値が代入されても、その値は更新可能。
新しい値を同じ変数名に代入することを「再代入」と呼び、以前の値は新しい値に置き換えられます。
変数の再代入は、プログラムの実行が進むにつれて、条件に応じて変数の内容を更新する場合に頻繁に使用されます。
Rubyの変数についての基本
ここではRubyの変数にどんな種類があるのか理解するために、変数の有効な範囲である変数スコープについて見ていきましょう!
Rubyの変数の種類
Rubyにおける変数の種類は次の通りです。
- ローカル変数
- グローバル変数
- インスタンス変数
- クラス変数
- 擬似変数
変数のスコープについて
スコープとは変数の有効な範囲です。
その変数がスコープの外に出てしまえば参照できず、たとえ名前が同じであっても違う変数として扱われます。
変数の種類が違えばスコープの範囲も違いますのでしっかりと押さえておきましょう!
変数のスコープについてもっと詳しく知りたい方は「Rubyにおけるスコープのおはなし」が参考になります。
ローカル変数とグローバル変数について
ここでは有効な範囲の小さいローカル変数と有効な範囲の大きいグローバル変数について見ていきましょう!
ローカル変数について
- 定義の仕方:小文字もしくは_で始めます。
- 定義の例:name
- 変数のスコープ:その変数が宣言されたブロック、メソッド定義、クラス定義の終わりまで。定義された場所でしか参照できない極めて局所的な変数。
- スコープの例:
class Human
name = “テック太郎”
def myName
puts name
end
end
human = Human.new
human.myName
myNamメソッドの外でname変数を宣言しても、myNameメソッドの中からは参照できないのでエラーが出ます。
グローバル変数について
- 定義の仕方:$を先頭に記述します。
- 定義の例:$name
- 変数のスコープ:グローバル変数はプログラムのどこからでも参照でき、同じ名前であれば必ず同じ変数として扱われます。
注意点としてグローバル変数は一般的に好まれません。
プログラム全体のどこからでも変更できるため、大きなプログラムではグローバル変数を利用することによってプログラムが必要以上に複雑になったりプログラムの流れを追ったり修正を加えたりするのが大変になったりするからです。 - 注意点
グローバル変数には使用の注意点があります。
1.どこからでも変更可能できてしまう
グローバル変数はプログラム全体で値を変更できるため、予測しづらいバグが発生しやすくなります。
2.プログラムの複雑化
大規模なプログラムでは、複数の場所からグローバル変数が変更される可能性があるため、コードを理解しにくくなります。
3. 保守の難しさ
複数の箇所で使用されるため、プログラムの流れを追ったり修正を加えたりするのが難しくなります。 - スコープの例:
$name = "テック二郎"
class Human
myName
$name = "テック太郎"
"./sample"#ここで別のファイルを読み込み、その中で$nameの値を変更してみる
$name
end
end
human = Human.new
human.myName #出力結果は「テック二郎」でした
出力された$nameの値はテック二郎に変わっていたので、別のファイルでも、読み込んで自分のプログラムの一部として実行すると、グローバル変数は参照できていて値を変更できているということがわかります。
ローカル変数とグローバル変数の違い まとめ
- ローカル変数は変数の有効な範囲(変数のスコープ)が局所的(ローカル)で、
有効な範囲を越えていれば同じ名前の変数でも違う変数として扱われる。 - グローバル変数はプログラム中のどこで使われても、同じ名前であれば、必ず同じ変数として扱われる。
この記事のハッシュタグ
クラス変数とインスタンス変数について
ここではインスタンス間でも値が共有されるクラス変数とインスタンス毎に値の異なるインスタンス変数を見ていきましょう!
インスタンス変数について
- 定義の仕方:@を先頭に記述します。
- 定義の例:@name
- 変数のスコープ:ローカル変数はメソッドごとに異なる変数として扱われましたが、インスタンス変数は同じインスタンス内であればメソッドの定義を越えてその値を参照したり変更したりできます。
- スコープの例:
class Human
def initialize(name)
@name = name
end
def myName
puts "私の名前は#{@name}です。"
end
end
human1 = Human.new("テック太郎")
human1.myName #"私の名前はテック太郎です。"
human2 = Human.new("テック二郎")
human2.myName #"私の名前はテック二郎です。"
initializeメソッドの中で宣言した@name変数をmyNameメソッドの中からも参照できることがわかります。
さらにhuman1とhuman2でインスタンスごとに違う値を持てることがわかります。
クラス変数について
- 定義の仕方:@@を先頭に記述します。
- 定義の例:@@name
- スコープ:そのクラスのすべてのインスタンスから参照したり値を変更したりできます。
- スコープの例:
class Human
def initialize(name)
@@name = name
end
def myName
puts "私の名前は#{@@name}です。"
end
end
human1 = Human.new("テック太郎")
human1.myName #"私の名前はテック太郎です。"
human2 = Human.new("テック二郎")
human2.myName #"私の名前はテック二郎です。"
human1.myName #"私の名前はテック二郎です。"
異なるインスタンス間でも@@nameの値が共有されているのがわかります。
インスタンス変数とクラス変数の違い まとめ
- クラス変数はクラスメソッド内とインスタンスメソッド内、両方で使える。
- クラス変数はクラスで1つの値で、どのインスタンスで使っても同じ値。
- インスタンス変数はインスタンスメソッド内でのみ、使用可能。
- インスタンス変数はインスタンスごとに値が異なる。
擬似変数について
通常の変数以外に疑似変数と呼ばれる特殊な変数があります。擬似変数の値は変更することができません。
擬似変数に何か代入しようとすると文法エラーになります。ここではself,true,false,nilを見ていきます。
selfについて
インスタンスメソッドの中で、メソッドのレシーバ自身を参照するにはselfという特別な変数を使用します。
class Human
def name
puts "私の名前はテック太郎です。"
end
def sayHello
self.name
end
end
human = Human.new()
human.sayHello
sayHelloメソッドで使用しているself.nameはsayHelloメソッドを呼んだ時のレシーバを参照しています。
つまりhumanインスタンスです。
またレシーバを省略してメソッドを呼ぶと暗黙的にselfをレシーバとします。そのため上記のコードのself.nameはnameと記述することもできます。
true,falseについて
例えばif文などで条件式を記述するとします。
「AとBが等しい」とか「AがBより大きい」などの条件が条件式に記述されます。
この式が評価され条件として成立する場合true、成立しない場合にfalseを返します。
x = 1
y = 2
if x < y == true
puts "true"
elsif x < y == false
puts "false"
end
上記のコードの場合はxよりyの方が大きいのでtrueが返ってきます。
なのでif文でtrueとfalseの場合分けをしてみると当然trueなのでその中身が実行されます。
nilについて
nilはオブジェクトが存在していないことを表すために使用されます。
何もオブジェクトが代入されていない変数にはnilが代入されているとして扱われます。
式展開について
Rubyでの式展開は、文字列中にRubyのコードを挿入し、実行結果を直接文字列に組み込む手法です。
具体的には、ダブルクォート(”)で囲まれた文字列内で「#{}」を使用し、変数や式を挿入します。
この機能を利用することで、文字列内に動的に変数の値や計算結果を埋め込めるのです。
たとえば、変数ageが30という値を持っている場合、式展開を使用して “彼の年齢は #{age} 歳です” と記述することで、「彼の年齢は 30 歳です」という文字列を生成できます。
この方法は、プログラム内で変化するデータを扱う際に有効であり、コードの可読性や保守性を向上させる効果があるでしょう。
また、式展開は変数の値だけでなく、任意のRuby式の評価もサポート。
例えば、計算式 #{10 * 5} を式展開することで、「50」という結果を文字列中に直接表示できます。
この柔軟性により、Rubyのプログラマーは複雑な文字列組み立てを、シンプルに実装することが可能になるのです。
そのほかの変数
そのほかの覚えておくと便利な変数についても紹介していきます。
- 定数
- ブロック変数
- クラスインスタンス変数
定数
定数は、プログラム実行中に値が変更されない変数です。
Rubyでは、定数は大文字アルファベットで始まる名前で宣言されますが、慣例的に全て大文字を使用します。
例えば、MAX_LIMIT = “100”と宣言することで、この定数はプログラム内で変更不可の値として扱われます。
ただし、Rubyの特性として、定数に対して新しい値を代入すること自体は可能ですが、警告が発生します発生。
変更を完全に防ぎたい場合は、オブジェクトにfreeze メソッドを適用することが推奨されます。
freezeメソッドはオブジェクトの状態を凍結し、そのオブジェクトへの変更を完全に防ぐ機能を持ちます。これにより、定数として扱うオブジェクトが誤って変更されることを防ぎます。
たとえば、以下のように使用します:
MAX_LIMIT = "100".freeze
# MAX_LIMITに新しい値を代入しようとするとエラーが発生します
# 例: MAX_LIMIT = “200” -> エラーが発生
このように既にfreezeされているオブジェクトに対して変更操作を行おうとすると、エラーが発生し、プログラムが中断されます。これにより、プログラムの動作が予期せず変わることを防ぐことができます。
ブロック変数
ブロック変数は、特定のコードブロック内でのみ有効な一時的な変数です。
例えば、Rubyのイテレーションメソッド内で使用されるこれらの変数は、ブロックの実行中にのみアクセス可能であり、ブロック外では参照できません。
具体的な使用例として、5.times do |index| では、index がブロック変数として機能し、各イテレーションでその値が更新されます。
ブロック変数は、ループやイテレーション内の一時的な操作に非常に有用です。
クラスインスタンス変数
クラスインスタンス変数は、クラス自身に属するが、そのクラスのインスタンスには属さない変数です。
これらは、クラスレベルで情報を保持するために使用され、インスタンス間で共有されません。
例として、class Car 内に@fuel_efficiency = “high”と宣言した場合、この変数はクラスメソッド内で参照可能ですが、インスタンスメソッドからはアクセスできません。
class Car
@fuel_efficiency = "high" # クラスインスタンス変数の宣言
def self.fuel_efficiency
@fuel_efficiency # クラスメソッドからアクセス可能
end
def show_fuel_efficiency
self.class.fuel_efficiency # インスタンスメソッドからアクセスするためにクラスメソッドを使用
end
end
puts Car.fuel_efficiency # 出力: high
car = Car.new
puts car.show_fuel_efficiency # 出力: high
クラスインスタンス変数は、クラスに固有の状態を保持するのに役立ちますが、継承されたサブクラスからはアクセスできないため、使用時には注意が必要です。
class Vehicle
@type = "generic vehicle" # スーパークラスのクラスインスタンス変数
def self.type
@type
end
end
class Car < Vehicle
@type = "car" # サブクラスのクラスインスタンス変数
end
puts Vehicle.type # 出力: generic vehicle
puts Car.type # 出力: car
この例では、Vehicle クラスが持つクラスインスタンス変数 @type は、サブクラスの Car からは継承されず、Car クラス内で別途定義された @type が利用されます。
クラスインスタンス変数とクラス変数の違い
クラスインスタンス変数はクラスレベルで独立して管理されるのに対し、クラス変数(@@ で始まる変数)は同じクラス階層内で共有されます。
class Vehicle
@@all_vehicles = 0 # クラス変数
def self.increment_vehicles
@@all_vehicles += 1
end
def self.total_vehicles
@@all_vehicles
end
end
class Car < Vehicle; end
class Bike < Vehicle; end
Vehicle.increment_vehicles
Car.increment_vehicles
Bike.increment_vehicles
puts Vehicle.total_vehicles # 出力: 3
puts Car.total_vehicles # 出力: 3
puts Bike.total_vehicles # 出力: 3
このように、クラス変数は継承されたサブクラス間で共有されますが、クラスインスタンス変数はそのクラス単位で独立して管理されます。
Rubyの変数と特徴 まとめ
以上が変数についての基本でした。
あなたがこれからRubyを上達するために変数の違いを理解することは非常に重要です。
その中でも定義の仕方や変数のスコープに違いがあるのでしっかり押さえましょう!
Rubyの変数についてもっと詳しく知りたい方はこちらどうぞ!
Ruby公式サイト:https://www.ruby-lang.org/ja/
はじめての転職、何から始めればいいか分からないなら
「そろそろ転職したいけれど、失敗はしたくない……」そんな方へ、テックキャンプでは読むだけでIT転職が有利になる限定資料を無料プレゼント中!
例えばこのような疑問はありませんか。
・未経験OKの求人へ応募するのは危ない?
・IT業界転職における“35歳限界説”は本当?
・手に職をつけて収入を安定させられる職種は?
資料では、転職でよくある疑問について丁寧に解説します。IT業界だけでなく、転職を考えている全ての方におすすめです。
「自分がIT業界に向いているかどうか」など、IT転職に興味がある方は無料カウンセリングにもお気軽にお申し込みください。