2012-02-16 12 views
35

私はRubyの新機能です(私は実際にはC#devです)。この質問はnoobのものかもしれません。 私は以下のようなクラスを持っていて、メソッド変数をたくさん使うのを避けるためにインスタンス変数(配列)を使用しました。クラスメソッドでのインスタンス変数の使用 - Ruby

これは私が期待したとおりに機能しますが、それは良い習慣ですか? 実際に私はそれがうまくいくとは思っていませんでしたが、クラスメソッドは他の言語の静的メソッドとして動作していないと思いますので、それが良い習慣であるか、クラス変数としてこれらの変数をすべてをつまむ。

class DummyClass 
    def self.dummy_method1 
    @arr = [] 
    # Play with that array 
    end 

    def self.dummy_method2 
    # use @arr for something else 
    end 
end 

答えて

58

インスタンス変数がRubyのクラスで動作する理由は、Rubyクラスインスタンス(Classのインスタンス)です。 DummyClass.classを調べて、自分で試してみてください。 RubyのC#の意味には「静的メソッド」はありません。なぜなら、すべてのメソッドはあるインスタンスで定義されている(または継承されている)ため、インスタンスによって呼び出されるからです。したがって、これらのインスタンス変数は、どのようなインスタンス変数も、呼び出し先で使用可能なものにアクセスできます。

DummyClassはインスタンスなので、独自のインスタンス変数を持つことができます。クラスへの参照を持っている限り、これらのインスタンス変数にアクセスすることもできます(クラス名は定数なので常にそうでなければなりません)。いつでも、::DummyClass.instance_variable_get(:@arr)を呼び出して、そのインスタンス変数の現在の値を取得することができます。

それが良いことであるかどうかは、方法によって異なります。

論理的にインスタンス/クラスDummyClassの "状態"の場合は、インスタンス変数に格納します。操作のショートカットとしてがdummy_method2でのみ使用されている場合は、それを引数として渡します。インスタンス変数アプローチを使用する例を示すには、RailsでActiveRecordを検討してください。

u = User.new 
u.name = "foobar" 
u.save 

ここで、ユーザーに割り当てられた名前は、正当なユーザーのデータです。 #saveコールの前に、「この時点でユーザーの名前は何ですか」と尋ねる場合は、「foobar」と答えます。内部を十分に掘り下げると(非常に遠くからメタプログラミングの多くが掘り起こされますが、インスタンス変数を使ってこれを行うことができます)。

私が使用した例では、2つの別々の公開呼び出しが含まれています。呼び出しが1回しか行われたにもかかわらずインスタンス変数がまだ使用されている場合は、#update_attributesのActiveRecord実装を見てください。メソッド本体は単にload(attributes, false) && saveです。#saveは、UPDATE users SET name='foobar' WHERE id=1;のような保存場所に保存されているにもかかわらず、(新しいnameのような)引数を渡されないのはなぜですか?名前のようなものは、インスタンスに属する情報なので、それがあります。

逆に、インスタンス変数を使用する意味がない場合を見ることができます。 #link_to_ifの実装を見てください。これは、通常はリンク先のURLなど、#link_toで受け入れられる引数の横にboolean-ish引数(通常はソースコード内の式)を受け入れるメソッドです。ブール条件がtrueyの場合、残りの引数を#link_toに渡して呼び出す必要があります。ここでインスタンス変数を代入するのは当然のことではありません。なぜなら、ここで呼び出すコンテキスト(レンダラー)にインスタンス内の情報が含まれているとは言わないからです。レンダラー自体には "リンクするURL"がありません。そのため、インスタンス変数に埋め込まれるべきではありません。

+1

良い例であるかどうかの例を挙げて、この素晴らしい説明をありがとう。 – tackleberry

16

これらは、クラスのインスタンス変数であり、ルビーでは完全に合法的なものです:クラスはあまりにもオブジェクト(クラスのインスタンス)であり、そのインスタンス変数を持っています。

各サブクラスにはそれぞれ独自のクラスインスタンス変数が設定されています(これらはすべて異なるオブジェクトです)。DummyClassをサブクラス化した場合、サブクラスのクラスメソッドは@arrを表示できません。

もちろん、クラス変数(@@foo)は、他の方法でも同じです。クラス階層全体が同じクラス変数を共有します。

+0

hmm thats something something。だから私は新しいクラスを継承しない限り、それは心配しません。それは良いニュース、ありがとう! – tackleberry

関連する問題