2009-07-02 44 views
82

一般に、名前が文字列にあるオブジェクトへの参照を取得するにはどうすればよいですか?名前が与えられたインスタンス変数の値を取得

具体的には、パラメータ名のリストがあります(メンバー変数は動的に構築されているため、直接参照することはできません)。

各パラメータは、from_sメソッドも持つオブジェクトです。私は(...もちろん動作しません)、次のような何かやりたい

:インスタンス変数の名前からインスタンス変数を取得するには

define_method(:from_s) do | arg | 
    @ordered_parameter_names.each do | param | 
     instance_eval "field_ref = @#{param}" 
     field_ref.from_s(param) 
    end 
end 

答えて

157

インスタンスの値を返します。

+またはinternを使用する必要はありません。 Rubyはこれをうまく処理します。しかし、自分自身が別のオブジェクトに到達し、その象牙を引き抜くと、カプセル化が壊れている可能性があります。

明示的にivarにアクセスしたい場合は、それをアクセサにすることが適切です。次のことを考えてみましょう:あなたはComputer.newをした場合は、この場合には

class Computer 
    def new(cpus) 
    @cpus = cpus 
    end 
end 

、あなたは@cpusで取得するためにinstance_variable_getを使用するように強制されるだろう。しかし、これをやっているのなら、おそらく@cpusが公開されていることを意味します。あなたがすべきことは:Computer.new(4).cpusです。

class Computer 
    attr_reader :cpus 
end 

今できることはComputer.new(4).cpusです。

既存のクラスを再度開き、リーダーにプライベートivarを作成することができます。アクセサーは単なるメソッドなので、

+0

instance_variable_get( "@#{name}")は変数の値を返しませんか?私は実際のオブジェクトへの参照が必要です。 多くの変数+名前を持つ配列を私が望む順番に並べ替えるのではなく、パラメータ自体を配列に入れました(設計の決定は、配列を検索するたびに変数にアクセスするか、 –

+0

Nope:instance_variable_get( "@#{name}")は、実際のオブジェクトを返します。 –

+0

もう少し明瞭にデッドスレッドを発見してください。 完全な例は次のようになります。 クラスコンピュータ attr_read:CPUの デフ新しい(のCPU) @cpus = CPUの エンド エンド ? –

7

は行います

name = "paramName" 
instance_variable_get(("@" + name).intern) 

これは、これを実現するための最も慣用的な方法がある@paramName変数

+0

動的にクラスを作成する際に、インスタンス変数名の配列があります(特定の順序で処理する必要があるため、このリストが必要です)。この名前を使用することで、変数への参照を取得します。 –

+1

私は文字列 "paramName"を持ち、@ paramNameへの参照が必要です –

+1

OK。あなたの質問を編集して、その2つのコメントを正確に言うことをお勧めします。 –

関連する問題