次のようなクラスがあり、インスタンス変数(配列)を使用して、多くのメソッドパラメーターを使用しないようにしました。
期待どおりに動作しますが、それは良い習慣ですか?実際、それが機能するとは期待していませんが、他の言語ではクラスメソッドが静的メソッドとして機能していないと思います。
class DummyClass
def self.dummy_method1
@arr = []
# Play with that array
end
def self.dummy_method2
# use @arr for something else
end
end
インスタンス変数がRubyのクラスで機能する理由は、Rubyクラスareインスタンス自体(クラスのインスタンス Class )。_DummyClass.class
_を調べて自分で試してみてください。C#の意味で「Ruby」には「静的メソッド」はありません。 (または継承されて)あるインスタンスで呼び出され、したがって、呼び出し先で使用可能なインスタンス変数にアクセスできます。
DummyClass
はインスタンスであるため、独自のインスタンス変数を持つことができます。クラスへの参照がある限り、これらのインスタンス変数にアクセスすることもできます(クラス名は定数であるため、常にそうする必要があります)。どの時点でも、::DummyClass.instance_variable_get(:@arr)
を呼び出して、そのインスタンス変数の現在の値を取得できます。
それが良いことかどうかについては、メソッドに依存します。
_@arr
_が論理的にインスタンス/クラスDummyClass
の「状態」である場合、インスタンス変数に格納します。 _@arr
_が_dummy_method2
_で操作上のショートカットとしてのみ使用されている場合は、引数として渡します。インスタンス変数アプローチが使用される例を示すために、RailsのActiveRecordを検討してください。これを行うことができます:
_u = User.new
u.name = "foobar"
u.save
_
ここで、ユーザーに割り当てられている名前は、ユーザーに合法的に存在するデータです。 _#save
_呼び出しの前に、「この時点でユーザーの名前は何ですか」と尋ねた場合、「foobar」と答えます。内部を深く掘り下げると(非常に深く掘り下げて多くのメタプログラミングを掘り下げることになりますが、まさにこのためにインスタンス変数を使用していることがわかります)。
私が使用した例には、2つの個別のパブリック呼び出しが含まれています。呼び出しが1回だけ行われたにもかかわらず、インスタンス変数がまだ使用されている場合を見るには、 _#update_attributes
_ のActiveRecord実装を見てください。メソッド本体は単純にload(attributes, false) && save
です。 _#save
_のようなsaveの本体にあるにもかかわらず、_UPDATE users SET name='foobar' WHERE id=1;
_に引数(新しいname
など)が渡されないのはなぜですか?名前のようなものはインスタンスに属する情報だからです。
逆に、インスタンス変数を使用しても意味がない場合を見ることができます。 _#link_to_if
_ の実装を見てください。これは、_#link_to
_によって通常受け入れられる引数とともに、ブール値のような引数(通常はソースコードの式)を受け入れるメソッドです。リンク先のURL。ブール条件が真である場合、残りの引数を_#link_to
_に渡して呼び出す必要があります。ここで呼び出しコンテキスト(レンダラー)がインスタンスにその情報を含むとは言わないので、ここにインスタンス変数を割り当てることはあまり意味がありません。レンダラー自体には「リンクするURL」がないため、インスタンス変数に埋め込まないでください。
これらはクラスインスタンス変数であり、Rubyでは完全に正当なものです。クラスもオブジェクト(クラスのインスタンス)なので、インスタンス変数もあります。
注目すべきことは、各サブクラスが独自のクラスインスタンス変数のセットを持っていることです(これらはすべて異なるオブジェクトであるため):DummyClass
をサブクラス化すると、サブクラスのクラスメソッドは@arr
。
クラス変数(@@foo
)はもちろん逆です:クラス階層全体が同じクラス変数を共有します。