Rubyのインスタンス変数、クラス変数、クラスインスタンス変数
Ruby のクラスには
があって何かとややこしい。。
特にクラス変数とクラスインスタンス変数の違いについてはいまいち理解しきれていなかったので、今回は頭の整理もかねてメモです。
それぞれの特徴について書いてみたいと思います。
インスタンス変数
オブジェクト固有の状態を保持するための変数。@をつける。
class Foo attr_accessor :instance_foo def initialize @instance_foo = 'instance_foo!' end end Foo.new.instance_foo #=> instance_foo!
外部からアクセスするにはFoo#name
とFoo#name=
を定義する必要があるが、attr_accessor
を使えば自動的に定義してくれる。
もしくはinstance_variable_get
とかinstance_variable_set
とか使う。
クラス変数
クラスとそのサブクラスの定義中、クラスメソッド、インスタンスメソッドで共有できる変数。
@@をつける。
class ParentFoo @@class_foo = 'class_foo!' def self.say @@class_foo end end class ChildFoo < ParentFoo def say @@class_foo end end ParentFoo.say #=> class_foo! ChildFoo.say #=> class_foo! ChildFoo.new.say #=> class_foo!
今回はsay
メソッドを用意してるけど、class_variable_get
とかclass_variable_set
とかで外部からアクセスもできる。
Rails を使ってるならcattr_accessor
でattr_accessor
的にクラス変数を外部に公開したりもできるはず。
クラスインスタンス変数
Ruby ではすべてがオブジェクトなので、クラスもClass
クラスのオブジェクト。つまりクラスオブジェクト自体もインスタンス変数を持つことができる。これがクラスインスタンス変数。
クラス定義式、クラスメソッドなど、self
がクラスを指すコンテキスト内で定義可能。
class ParentFoo @class_instance_foo = 'class_instance_foo!' def say @class_instance_foo end def self.say @class_instance_foo end end class ChildFoo < ParentFoo ; end ParentFoo.say #=> 'class_instance_foo!' ParentFoo.new.say #=> nil ChildFoo.say #=> nil ChildFoo.new.say #=> nil
クラス変数との明確な違いは以下の2点かなと思われる。
まとめ
それぞれの特徴を把握して、明確な意図を持って使い分けていきたいですね。
今回は以下の書籍を参考にしました。