17 Jun 2010

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

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

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


class MyClass
@@class_var = true
@class_instance_var = true

def initialize
@instance_var = true
end

# Class Variableを取得
def self.class_method
return @@class_var, @class_instance_var, @instance_var
end

# Instance Variableを取得
def instance_method
return @@class_var, @class_instance_var, @instance_var
end
end

# 派生クラス
class Derived < MyClass; end


p MyClass.class_method # => [true, true, nil]
p Derived.class_method # => [true, nil, nil]

p MyClass.new.instance_method # => [true, nil, true]
p Derived.new.instance_method # => [true, nil, true]


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

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

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

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



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


class MyClass
@class_instance_var = 0

def initialize(fnum)
@class_instance_var = fnum
end

# Class Variableを取得
def self.class_method
@class_instance_var
end

# Instance Variableを取得
def instance_method
@class_instance_var
end
end

m = MyClass.new 1
p m.instance_method # => 1

d = Derived.new 2
p d.instance_method # => 2
p m.instance_method # => 1

p MyClass.class_method # => 0
p Derived.class_method # => nil


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


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


.