1. ホーム
  2. ruby

[解決済み】Rubyのクラスインスタンス変数とクラス変数の比較

2022-04-20 17:47:06

質問

読む https://stackoverflow.com/questions/826734/when-do-ruby-instance-variables-get-set が、クラスのインスタンス変数をいつ使えばいいのか、二の足を踏んでいます。

クラス変数はクラスの全オブジェクトに共有され、インスタンス変数は1つのオブジェクトに属します。クラス変数がある以上、クラスインスタンス変数を使う余地はあまり残されていない。

どなたか、この2つの違いと使うタイミングを説明していただけませんか?

以下はコード例です。

class S
  @@k = 23
  @s = 15
  def self.s
    @s
  end
  def self.k
     @@k
  end

end
p S.s #15
p S.k #23

更新しました。 今、理解しました! クラスインスタンス変数は、継承チェーンに沿って渡されるものではありません。

どうすればいいですか?

クラス上のインスタンス変数。

class Parent
  @things = []
  def self.things
    @things
  end
  def things
    self.class.things
  end
end

class Child < Parent
  @things = []
end

Parent.things << :car
Child.things  << :doll
mom = Parent.new
dad = Parent.new

p Parent.things #=> [:car]
p Child.things  #=> [:doll]
p mom.things    #=> [:car]
p dad.things    #=> [:car]

クラス変数です。

class Parent
  @@things = []
  def self.things
    @@things
  end
  def things
    @@things
  end
end

class Child < Parent
end

Parent.things << :car
Child.things  << :doll

p Parent.things #=> [:car,:doll]
p Child.things  #=> [:car,:doll]

mom = Parent.new
dad = Parent.new
son1 = Child.new
son2 = Child.new
daughter = Child.new

[ mom, dad, son1, son2, daughter ].each{ |person| p person.things }
#=> [:car, :doll]
#=> [:car, :doll]
#=> [:car, :doll]
#=> [:car, :doll]
#=> [:car, :doll]

クラスのインスタンス変数(そのクラスのインスタンスではない)を使えば、サブクラスが自動的に取得することなく、そのクラスに共通の何かを格納することができます(逆もまたしかり)。クラス変数を使用すると、そのクラスで使用するために self.class をインスタンスオブジェクトから取得し、(望ましい場合には)クラス階層全体で自動的に共有することができます。


これらを統合して、インスタンス上のインスタンス変数もカバーする1つの例とします。

class Parent
  @@family_things = []    # Shared between class and subclasses
  @shared_things  = []    # Specific to this class

  def self.family_things
    @@family_things
  end
  def self.shared_things
    @shared_things
  end

  attr_accessor :my_things
  def initialize
    @my_things = []       # Just for me
  end
  def family_things
    self.class.family_things
  end
  def shared_things
    self.class.shared_things
  end
end

class Child < Parent
  @shared_things = []
end

そして実行中。

mama = Parent.new
papa = Parent.new
joey = Child.new
suzy = Child.new

Parent.family_things << :house
papa.family_things   << :vacuum
mama.shared_things   << :car
papa.shared_things   << :blender
papa.my_things       << :quadcopter
joey.my_things       << :bike
suzy.my_things       << :doll
joey.shared_things   << :puzzle
suzy.shared_things   << :blocks

p Parent.family_things #=> [:house, :vacuum]
p Child.family_things  #=> [:house, :vacuum]
p papa.family_things   #=> [:house, :vacuum]
p mama.family_things   #=> [:house, :vacuum]
p joey.family_things   #=> [:house, :vacuum]
p suzy.family_things   #=> [:house, :vacuum]

p Parent.shared_things #=> [:car, :blender]
p papa.shared_things   #=> [:car, :blender]
p mama.shared_things   #=> [:car, :blender]
p Child.shared_things  #=> [:puzzle, :blocks]  
p joey.shared_things   #=> [:puzzle, :blocks]
p suzy.shared_things   #=> [:puzzle, :blocks]

p papa.my_things       #=> [:quadcopter]
p mama.my_things       #=> []
p joey.my_things       #=> [:bike]
p suzy.my_things       #=> [:doll]