gold対策(模擬試験13)。
インスタンス間で共有され、かつ自分自身のクラスとサブクラスで管理される。
class A @@x = 0 class << self def x @@x end end def x @@x = 2 end end class B < A @@x = 3 end p A.x # >> 3
これだけでも気持ち悪いのですが、 もっと気持ち悪い例がメタプログラミングRuby(4.1.4)で紹介されています。 ちょっと変更して掲載すると
@@v = 1 # !> class variable access from toplevel class MyClass @@v = 2 def v @@v end end @@v # => 2 # !> class variable access from toplevel MyClass.new.v # => 2 @@v = 3 # !> class variable access from toplevel MyClass.new.v # => 3
トップレベルで定義するとwarningが出ます。
こんな使い方はしないはずですが global変数のようです。
一応、global変数とは違う例を載せておきます。下記だとエラーとなります。
class MyClass @@v = 2 end @@v # !> class variable access from toplevel # ~> -:4:in `<main>': uninitialized class variable @@v in Object (NameError)
こんな動きになるのは、
クラス変数がクラスに属していないからだ。 クラスではなく、クラス階層に属しているのだ。 @@vはmainのコンテキストで定義されているので、mainのクラスであるObjectに属していることになる。 それから、Objectのすべての子孫にも属しているかだ。 結局はみんなが同じクラス変数を共有しているというわけだ。
なるほど。試してみます。
class MyClass @@v = 2 end MyClass.class_variables => [:v] >> Object.class_variables => []
@@v = 1 class MyClass; end >> MyClass.class_variables => [:v] >> Object.class_variables => [:v]
これは、恐ろしい。
多くのRubyistはクラス変数を使わずにクラスインスタンス変数を使っている。
使わないに越したことはないですね。