かまたま日記3

プログラミングメイン、たまに日常

クラスインスタンス変数はそのクラスからしか参照できない

RubyのクラスはClassクラスのオブジェクトなので、インスタンス変数を持てます。クラスレベルとかクラスメソッドの中で定義された@付きの変数はクラスインスタンス変数(Class Instance Variable)と呼ばれ、そのクラスからしか参照できません、継承されてる場合、継承先でも参照できません。仕事中に継承しているクラスでBaseの値を参照しようとしてちょっとハマった次第であります。

バージョンは2.5.0です。

class Base
  def self.get
    @keys
  end

  def self.add(key)
    @keys ||= []
    @keys << key
  end

  add("Base")
end

class A1 < Base
  add("A1-1")
  add("A1-2")
end

class A2 < A1
  add("A2")
end

class B1 < Base
  add("B1")
end

class B2 < B1
  add("B2")
end

puts "Base=#{Base.get}"
puts "A1=#{A1.get}"
puts "A2=#{A2.get}"
puts "B1=#{B1.get}"
puts "B2=#{B2.get}"

出力はこんな感じになります。

Base=["Base"]
A1=["A1-1", "A1-2"]
A2=["A2"]
B1=["B1"]
B2=["B2"]

なので、継承ツリー上にある全部の @keys の値が欲しい場合、全部で get をしてやる必要があります。

p A2.ancestors.select{|k| k <= Base}.inject([]){|sum, k| sum + k.get}
=> ["A2", "A1-1", "A1-2", "Base"]