5

インスタンス変数が@fooあり、文字列を取得するコードを書きたい'foo'

ヒントはありますか?

4

4 に答える 4

7

オブジェクトへの参照しかない場合は、きれいに行うことはできません。

def foo
  bar @something
end

def bar(value)
  value # no clean way to know this is @something
end

私が考えることができる唯一のハックは、 のすべてのインスタンス変数をループしselfて、一致を探すことです。しかし、これは非常に厄介なアプローチであり、遅くなる可能性があります。

def bar(value)
  instance_variables.each do |ivar_name|
    if instance_variable_get(ivar_name) == value
      return ivar_name.to_s.sub(/^@/, '') # change '@something' to 'something'
    end
  end

  # return nil if no match was found
  nil 
end

@something = 'abc123'
bar @something # returns 'something'

# But passing the same value, will return a value it's equal to as well
bar 'abc123' # returns 'something'

これが機能するinstance_variablesのは、インスタンス変数の名前であるシンボルの配列を返すためです。

instance_variables
#=> [:@something, :@whatever] 

そしてinstance_variable_get、その名前で値を取得できます。

instance_variable_get :@something # note the @
#=> 'abc123'

2 つの方法を組み合わせると、目的に近づくことができます。


賢く使ってください。これに基づくソリューションを使用する前に、必要がないようにリファクタリングできるかどうかを確認してください。メタプログラミングは格闘技のようなものです。それがどのように機能するかを知っている必要がありますが、可能な限り使用しないように規律を持ってください。

于 2012-12-28T19:27:22.717 に答える
1

Ruby では、オブジェクトのみを操作できます。変数 (インスタンス変数を含む) はオブジェクトではありません。

さらに、この場合、マジックメソッドに何を返してもらいたいですか:

foo = Object.new
bar = foo
@baz = bar
@qux = bar

magic_method(foo) # what should the return value be and how would it know?
于 2012-12-28T20:18:07.463 に答える
1

このメソッドを呼び出してinstance_variables、オブジェクトのすべてのインスタンス変数の名前を取得できます。ただし、インスタンス変数は、初期化された後にのみそのリストに含まれることに注意してください。

>> class A; attr_accessor :foo; end
=> nil
>> a = A.new
=> #<A:0x103b310b0>
>> a.instance_variables
=> []
>> a.foo = 42
=> 42
>> a.instance_variables
=> ["@foo"]
于 2012-12-28T21:28:40.283 に答える