名前を指定してインスタンス変数の値を取得する


99

一般に、名前が文字列に含まれるオブジェクトへの参照を取得するにはどうすればよいですか?

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

各パラメーターは、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

回答:


179

これを実現する最も慣用的な方法は次のとおりです。

some_object.instance_variable_get("@#{name}")

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

明示的にivarにアクセスしたい場合、正しいことはそれをアクセサーにすることです。以下を検討してください。

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

この場合、あなたがそうした場合、あなたはに到達するためComputer.newに使用せざるinstance_variable_getを得なくなります@cpus。しかし、あなたがこれをしているなら、あなたはおそらく@cpus公になることを意味します。あなたがすべきことは:

class Computer
  attr_reader :cpus
end

今、あなたは行うことができますComputer.new(4).cpus

あなたが再度開くことに注意してください任意の既存のクラスをし、リーダーにプライベートIVARを作ります。アクセサーは単なるメソッドなので、次のことができますComputer.new(4).send(var_that_evaluates_to_cpus)


instance_variable_get( "@#{name}")は変数の値を返しませんか?実際のオブジェクトへの参照が必要です。多くの変数+必要な順序で名前が付いた配列を持つ代わりに、パラメータ自体を配列に入れました(設計上の決定は、配列を検索して毎回変数にアクセスするか、必要な場合にのみ使用される名前を持つ追加の配列)
LK__

いいえ、instance_variable_get( "@#{name}")は実際のオブジェクトを返します。
イェフダカッツ

少しわかりやすくするためにデッドスレッドを明らかにする。完全な例は次のようになります:クラスコンピューターattr_read:cpus def new(cpus)@cpus = cpus end end?
Nicolas de Fontenay 2013

「しかし、自分が別のオブジェクトに手を伸ばしてそのivarを引き出している場合、カプセル化が壊れている可能性はかなり高いです。」別のオブジェクトのivarに割り込むにはどうすればよいですか。
RubyMiner '19 / 11/15

9

インスタンス変数の名前からインスタンス変数を取得するには、次のようにします。

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

これはインスタンス変数の値を返します @paramName


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

1
「paramName」という文字列があり、@ paramNameへの参照が必要
LK__ 2009

1
OK。質問を編集して、これら2つのコメントを正確に伝えることをお勧めします。
ダニエルルークラフト2009

2
また、これは逆シリアル化とは何の関係もありません。より適切なタイトルは、「名前を指定してインスタンス変数の値を取得する」などです。
Daniel Lucraft 2009

いつでもモジュールを実行して追加:attr_reader varnameできるので、変数にアクセスできます。
ocodo
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.