せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】スーパークラスのインスタンス変数、クラスインスタンス変数

 
この本を読んでいます。

プログラミング言語 Ruby

プログラミング言語 Ruby


 

スーパークラスインスタンス変数

インスタンス変数は継承とは無関係。
変数宣言しなかったら、利用したタイミングでインスタンス変数として認識される。Rubyは動的にメソッドを追加する事については前に勉強したところ。
初めてattr_メソッドと出会ったところ。


スーパークラスのinitializeの実行によって、
Childクラスの特定のインスタンスに@xの変数が出現されるだけ。
クラスインスタンスは読み取れない。
そもそもParentオブジェクト、Childオブジェクトは何の関係もないから。

class Parent
  @xx = "hoge1"
  def initialize
    @x = "hoge2"
  end
  attr_accessor :x
end
class Child < Parent
  def get_x
    p @x
  end
  def get_xx;
    p @xx
  end
end
parent = Parent.new
child = Child.new
child.get_x  #<= hoge2
child.get_xx  #<= nil

親のインスタンス変数は上書きされる

スーパークラスインスタンス変数をシャドウイングしないので、親の状態も上書きされる「ようにみえる」。
(注)そもそも敬称とは別概念なので、本当に上書きされているわけではない。

class Parent
  def initialize
    @x = "hoge2"
  end
  def hello
    p @x
  end
  attr_accessor :x
end
class Child < Parent
  def set_x
    @x = "hoge3"
  end
end
child = Child.new
child.set_x
child.hello  #<= "hoge3"


 

インスタンス変数は全子孫で共有するわけではない

クラス変数は、全子孫で共有する。
クラス変数の説明の前に、まずインスタンス変数から。
それぞれの子孫クラスのインスタンスが見ているx変数は、別のものだから当然の結果。

(注)別の参照先なのだから共有できなくて当然なのであって
共有できる・できないの文脈で語ることは違和感があるかもしれない。
でも、クラスインスタンス変数とクラス変数の違いを考えるときに、
後者は「共有できる」性質を持つことが違いとして大きいので
あえて(不自然ではあるけれども)クラスインスタンス変数は共有できないことを確認している
(10月15日追記)

class Parent
  def initialize
    @x = "hoge2"
  end
  def hello
    p @x
  end
  attr_accessor :x
end
class Child < Parent
  def set_x
    @x << "hoge3"
  end
end
class Child2 < Parent
  def set_x
    @x << "hoge4"
  end
end
child = Child.new
child.set_x
child.hello  #<= "hoge2hoge3"

child2 = Child2.new
child2.set_x
child.hello  #<= "hoge2hoge3"
p child.x.object_id  #<= 24999840
p child2.x.object_id  #<= 24999336

 

クラス変数は全子孫で共有する

class Parent
  @@xxx = "huga1"
  def self.xxx
    @@xxx
  end
end
class Child < Parent
    @@xxx << "hoge3"
end
p Child.xxx  #<= "huga1hoge3"
class Child2 < Parent
    @@xxx << "hoge4"
end
p Child.xxx  #<= "huga1hoge3hoge4"
p Child2.xxx.object_id  #<= 26081832
p Parent.xxx.object_id  #<= 26081832

クラス定義もただの地の文というのは前にみたところ。