を使用class_variable_get
しますが、必要な場合に限ります
class_variable_get
それがあなたに「魅力的」ではないという事実を除いて、より良い方法です。クラス内に到達してカプセル化を破っている場合は、何か間違ったことをしていることを示すために、この追加のバリアを設けることが適切である可能性があります。
アクセスする変数のアクセサメソッドを作成します
これらがクラスであり、変数にアクセスしてもカプセル化が壊れない場合は、それらのクラスアクセサーメソッドを作成して、より簡単できれいにする必要があります。
class Foo
def self.bar
@@bar
end
end
p Foo.bar
ただし、これがクラスの場合、クラス変数が必要ですか?影響を理解していない場合(以下を参照)、実際にはクラス自体のインスタンス変数が必要な場合があります。
class Foo
class << self
attr_accessor :bar
end
end
Foo.bar = 42
p Foo.bar
クラス変数の動作
クラス変数は、主に名前が原因で、クラスレベルで情報を格納する正しい方法のように初心者に表示されます。また、クラスのメソッドまたはインスタンスメソッドのどちらを使用していても、同じ構文を使用して読み取りと書き込みを行うことができるため、便利です。ただし、クラス変数はクラスとそのすべてのサブクラスの間で共有されます。
たとえば、次のコードについて考えてみます。
class Rectangle
def self.instances
@@instances ||= []
end
def initialize
(@@instances ||= []) << self
end
end
class Square < Rectangle
def initialize
super
end
end
2.times{ Rectangle.new }
p Rectangle.instances
#=> [#<Rectangle:0x25c7808>, #<Rectangle:0x25c77d8>]
Square.new
p Square.instances
#=> [#<Rectangle:0x25c7808>, #<Rectangle:0x25c77d8>, #<Square:0x25c76d0>]
わかった!長方形は正方形ではありません!同じことを行うためのより良い方法は次のとおりです。
class Rectangle
def self.instances
@instances ||= []
end
def initialize
self.class.instances << self
end
end
class Square < Rectangle
def initialize
super
end
end
2.times{ Rectangle.new }
p Rectangle.instances
#=> [#<Rectangle:0x25c7808>, #<Rectangle:0x25c77d8>]
2.times{ Square.new }
p Square.instances
#=> [#<Square:0x25c76d0>, #<Square:0x25c76b8>]
クラス自体にインスタンス変数とアクセサメソッドを作成することにより(これはたまたまクラスのインスタンスでありClass
、同様にMyClass = Class.new
)、クラスのすべてのインスタンス(および部外者)は、共有されていない情報を読み書きするための共通のクリーンな場所を持ちます他のクラス間。
作成されたすべてのインスタンスを明示的に追跡すると、「未使用」インスタンスでのガベージコレクションが防止されることに注意してください。上記のようなコードを慎重に使用してください。
class_eval
よりクリーンな方法で使用する
最後に、を使用する場合はclass_eval
、文字列を解析して評価する必要のないブロック形式もあることに注意してください。
Foo.class_eval('@@bar') # ugh
Foo.class_eval{ @@bar } # yum