一から勉強させてください

最下級エンジニアが日々の学びをアウトプットしていくだけのブログです

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

Ruby のクラスには

があって何かとややこしい。。

特にクラス変数とクラスインスタンス変数の違いについてはいまいち理解しきれていなかったので、今回は頭の整理もかねてメモです。

それぞれの特徴について書いてみたいと思います。

インスタンス変数

オブジェクト固有の状態を保持するための変数。@をつける。

class Foo
  attr_accessor :instance_foo

  def initialize
    @instance_foo = 'instance_foo!'
  end
end

Foo.new.instance_foo #=> instance_foo!

外部からアクセスするにはFoo#nameFoo#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_accessorattr_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点かなと思われる。

まとめ

それぞれの特徴を把握して、明確な意図を持って使い分けていきたいですね。

今回は以下の書籍を参考にしました。