2019-11-30
クラス変数とインスタンス変数
職場で「クラス変数とクラスインスタンス変数の違い」が話題にあがっていて、以前理解したよな、と思いつつ咄嗟に整理して述べられないなと思ったので、思い出しつつまとめてみる。
基本的にはクラス変数とインスタンス変数というものがある。
まずサンプルコード。
class Parent
@@var = 'class variable of Parent'
@var = 'instance variable of Parent (so called class instance variable)'
class << self
def at_at_var
@@var
end
def at_var
@var
end
end
def initialize
@var = 'instance variable of parent'
end
def at_at_var
@@var
end
def at_var
@var
end
end
インスタンス変数とは
あるインスタンスにおいて利用できる。@{変数名}
により指示される。
たとえば、parent という「Parent クラスのインスタンス変数をもっている。
parent = Parent.new
parent.at_var # => "instance variable of parent"
同様に、Parent という「Class クラスのインスタンス変数をもっている。
Parent.at_var # => “instance variable of Parent (so called class instance variable)”
後者のように「Class クラスのインスタンス変数」と呼ぶことがある。
クラス変数とは
あるクラスが保持する変数。@@{変数名}
により指示される。
当然ながら Parent クラスは自身のクラス変数を利用できる。
Parent.at_at_var # => "class variable of Parent"
クラス変数はこれに加えて、以下の特徴をもつ。
1. Parent クラスのインスタンスから、Parent クラスのクラス変数にアクセスできる
parent.at_at_var # => "class variable of Parent"
2. Parent クラスを継承した Child クラスから、継承元である Parent クラスのクラス変数にアクセスできる
class Child < Parent
def initialize
@var = 'instance variable of child'
end
end
Child.at_at_var # => "class variable of Parent"
3.
(上記の合わせ技として)Parenet クラスを継承した Child クラスのインスタンスから、Child クラスの継承元である Parent のクラス変数にアクセスできる
child = Child.new
child.at_at_var # => "class variable of Parent"
おまけ
仕組みはこれだけだと思う。最後に念のため、上で述べたクラス変数の「色んなところからアクセスできる性質」は、クラスインスタンス変数には与えられていないことを確認する。
1. Parent クラスのインスタンス変数にはアクセスできない
parent.at_var # => "instance variable of parent"
@var は parent のインスタンス変数を指してしまっている。
2. Parent クラスを継承した Child クラスから、継承元である Parent クラスのクラスインスタンス変数にはアクセスできない
Child.at_var # => nil
@var は「Child という Class クラスのインスタンス変数」を指してしまっている。(これは宣言していないのでnil
が返っている。)
3. Parenet クラスを継承した Child クラスのインスタンス変数にはアクセスできない
child.at_var # => "instance variable of child"
@var は child のインスタンス変数を指してしまっている。
丁寧にインスタンス変数」とか、どうしても早口言葉っぽくなるな…。
以上です。