17 Jun 2010

Ruby クラス変数、クラスインスタンス変数、インスタンス変数

kabakiyoさんの記事
- クラス変数とクラスインスタンス変数とインスタンス変数の違いについて

を読んで、クラスメソッドとインスタンスのメソッドを組み合わせたときクラス変数、クラスインスタンス変数、インスタンス変数が参照できるのかどうかよく理解してないことに気がついたのでサンプルを書いてみることにしました。

  1. class MyClass  
  2.   @@class_var = true  
  3.   @class_instance_var = true  
  4.   
  5.   def initialize  
  6.     @instance_var = true  
  7.   end  
  8.   
  9.   # Class Variableを取得  
  10.   def self.class_method  
  11.     return @@class_var@class_instance_var@instance_var  
  12.   end  
  13.   
  14.   # Instance Variableを取得  
  15.   def instance_method  
  16.     return @@class_var@class_instance_var@instance_var  
  17.   end  
  18. end  
  19.   
  20. # 派生クラス  
  21. class Derived < MyClass; end  
  22.   
  23.   
  24. p MyClass.class_method        # => [true, true, nil]  
  25. p Derived.class_method        # => [true, nil, nil]  
  26.   
  27. p MyClass.new.instance_method # => [true, nil, true]  
  28. p Derived.new.instance_method # => [true, nil, true]  


これを日本語でまとめると..

- クラスインスタンス変数
 - 定義の仕方は@name_of_variable。インスタンス変数とは定義する場所が違う(クラスの中、メソッドの外)。
 - 継承先のクラスから参照できない
 - インスタンスから参照できない

- クラス変数
 - 常に参照できる

- インスタンス変数
 - インスタンスからのみ参照できる



それでなんだか定義の記述が同じで場所が違うだけのクラスインスタンス変数とインスタンス変数の違いがなんだか分からなくなった。

  1. class MyClass  
  2.   @class_instance_var = 0  
  3.   
  4.   def initialize(fnum)  
  5.     @class_instance_var = fnum  
  6.   end  
  7.   
  8.   # Class Variableを取得  
  9.   def self.class_method  
  10.     @class_instance_var  
  11.   end  
  12.   
  13.   # Instance Variableを取得  
  14.   def instance_method  
  15.     @class_instance_var  
  16.   end  
  17. end  
  18.   
  19. m = MyClass.new 1  
  20. p m.instance_method # => 1  
  21.   
  22. d = Derived.new 2   
  23. p d.instance_method # => 2  
  24. p m.instance_method # => 1  
  25.   
  26. p MyClass.class_method # => 0  
  27. p Derived.class_method # => nil  


- クラスインスタンス変数
 - インスタンスから参照した場合、インスタンス変数がそのインスタンスのスコープでクラスインスタンス変数を上書く
 - クラスメソッドから参照した場合、定義したクラスからのみ参照可能


というわけで、クラスインスタンス変数は継承されるときに継承先にコピーされないんだろうと理解したけど、このあたり本当のところご存知の方いらっしゃいます?


.