クラス インスタンス変数は、一般に、クラス変数よりも便利で意外性が低いため、おそらくそれらを使用する必要があります。
ここで、StackOverflow に関する Ruby の回答に期待される、耐え難いほど詳細にいくつかのことを説明します。
クラス インスタンス変数を宣言または参照するには、クラス スコープ内にいて、単一の @ 記号を使用する必要があります。これにより、そのクラスのシングルトン クラス インスタンスに変数が配置されます。
残念ながら、クラス スコープ内でキーワードを使用すると、メソッドはそのクラスのインスタンス メソッドdef
のリストに配置され、インスタンス スコープ内で実行されるため、@ 記号変数はそれらが存在するインスタンス上にあります。 .
代わりに、インスタンスではなく、クラスでメソッドを定義する必要があります。これが実際に意味することは、これらのメソッドがクラス オブジェクトのシングルトン クラスのインスタンス メソッドのリストにあるということです。(ふぅ!)
要約すると、クラス object のシングルトン クラスでメソッドを切り替えて定義するには、少なくとも 4 つのイディオムがありますFoo
。
class Foo
@a, @b, @c, @d = 1, 2, 3, 4
# 1. pass the target to def
def Foo.a
@a
end
# 2. pass the target to def, relying on the fact that self
# happens to be the class object right now
def self.b
@b
end
# switch from class scope to singleton class scope
class << self
# 3. define a plain accessor in singleton class scope
def c
@c
end
# 4. use a macro to define an accessor
attr_reader :d
end
end
p [Foo.a, Foo.b, Foo.c, Foo.d]
#=> [1, 2, 3, 4]
(考慮に入れれば、これを行う方法はおそらく他にも 6 つ以上ありますがclass_eval
、define_method
今のところはそれで満足するはずです。:-))
最後に 1 つ: クラス インスタンス変数は、それらが定義されているクラスを介してのみ使用できます。サブクラスから (またはサブクラスを介して) これらのメソッドのいずれかを呼び出そうとすると、メソッドは実行されますが、@ 変数はすべて nil になりself
ます。
class Bar < Foo
end
p [Bar.a, Bar.b, Bar.c, Bar.d]
#=> [nil, nil, nil, nil]