こんにちは。アルバイトの大木です。普段プログラミングをしていて何気なく使っている変数ですが、スコープを意識して使っていますか?スコープと言うとかっこよく聞こえますが、要するに、変数にアクセスできる範囲のことです。この範囲は変数の種類によって異なります。

Rubyの4種類の変数定義方法

ルーターはクローリング会社として、nokogiriやselenium/mechanizeの使いやすさからRubyを共通言語として採用しています。 例えば、Rubyだと主に以下の4種類の変数があります。

ローカル変数

rooter = "ルーター"
変数と聞くと思い浮かべるのはこのローカル変数ではないでしょうか?スコープは、変数が宣言されたブロック、メソッドやクラス定義の終わりまでです。
class Company
  rooter = "ルーター"
  def syoukai
    puts rooter + "です"
  end
end

company = Company.new
company.syoukai #undefined local variable or method `rooter' 

このように、ローカル変数はメソッドをまたいでアクセスすることはできません。

インスタンス変数

@rooter = "ルーター"
このように、@をつけることで表現できます。スコープは同じインスタンスの範囲内です。なので、インスタンスごとに値を持ちます。
class Company
  def initialize(rooter)
    @rooter = rooter
  end
  def syoukai
    puts @rooter + "です"
  end
end

company_name = Company.new("ルーター")
company_work = Company.new("スクレイピング")
company_name.syoukai #ルーターです
company_work.syoukai #スクレイピングです
このように、クラス内のインスタンスメソッドからアクセスすることができました。

クラス変数

@@rooter = "ルーター"
このように@@をつけることで表現できます。スコープはそのクラスの全てのインスタンスです。しかし、クラス変数はクラス内に一意に値を持つ変数です。
class Company
  def initialize(rooter)
    @@rooter = rooter 
  end 
  def syoukai
    puts @@rooter + "です" 
  end
end 
company_name = Company.new("ルーター")
company_work = Company.new("スクレイピング") 
company_name.syoukai #スクレイピングです
company_work.syoukai #スクレイピングです
つまり、インスタンス変数とは違って、変数の値が上書きされてしまいます。 インスタンス変数とクラス変数は似ていますが、インスタンスごとに違った値を与えたいときはインスタンス変数を使うなど使い分けていく必要がありそうです。

クラスインスタンス変数

4つ目はクラスインスタンス変数という一番凄そうな変数です。その名の通り、クラス変数にもインスタンス変数にも似た特徴を持っています。見た目はインスタンス変数と同じように@をつけて表現しますが、クラス変数と似たような働きをします。しかし、そのクラスでしかアクセスできません。
class Company
  @rooter = "ルーター"
  def syoukai
    puts @rooter
  end
  def self.intro
    puts @rooter
  end
end

class Office < Company
end
Company.intro #ルーター
company = Company.new
company.syoukai #nil
Office.intro #nil
1つ目の出力結果のようにクラスメソッドからクラスインスタンス変数はアクセスできるが、2つ目はクラスインスタンス変数がインスタンス変数と見なされ、インスタンスメソッドからクラスインスタンス変数はアクセスできません。3つ目が特徴で、継承されたクラスからクラスインスタンス変数はアクセスできないことを示しています。

まとめ

自分はローカル変数とインスタンス変数しか意識していなかったのですが、調べてみるといろいろな変数がありました。普段からスコープを意識して変数を使っていきたいですね。