23

クラスがあるとしますA

class A
  attr_accessor :x, :y

  def initialize(x,y)
    @x, @y = x, y
  end
end

どのように名前が付けられたかを正確に知らなくてもx、属性を取得するにはどうすればよいですか。y

例えば

a = A.new(5,10)
a.attributes # => [5, 10]
4

6 に答える 6

36

内省してください、ルーク!

class A
  attr_accessor :x, :y

  def initialize(*args)
    @x, @y = args
  end

  def attrs
    instance_variables.map{|ivar| instance_variable_get ivar}
  end
end

a = A.new(5,10)
a.x # => 5
a.y # => 10
a.attrs # => [5, 10]
于 2012-04-04T07:46:40.480 に答える
16

Sergioの答えは役に立ちますが、OPの質問を正しく理解していれば、すべてのインスタンス変数が返されます。

ミューテーターなどを持つ「属性」のみを返したい場合は、次のような少し複雑なことを行う必要があります。

attrs = Hash.new
instance_variables.each do |var|
  str = var.to_s.gsub /^@/, ''
  if respond_to? "#{str}="
    attrs[str.to_sym] = instance_variable_get var
  end
end
attrs

これは、attr_accessor (または手動で作成されたミューテーター) で宣言された属性のみを返し、内部インスタンス変数を隠したままにします。attr_reader で宣言したものが必要な場合は、同様のことができます。

于 2014-03-02T18:38:31.890 に答える
13
class A
  ATTRIBUTES = [:x, :y]
  attr_accessor *ATTRIBUTES

  def initialize(x,y)
    @x, @y = x, y
  end

  def attributes
    ATTRIBUTES.map{|attribute| self.send(attribute) }
  end
end

これは DRY-est ではないかもしれませんが、(すべてが継承される基本クラスではなく) 1 つのクラスに対してのみこれを行うことに関心がある場合は、これでうまくいくはずです。

于 2016-08-11T07:12:22.253 に答える
1

attr_accessor を使用してクラス内の属性を定義する場合、Ruby では refexion を使用して、宣言された属性ごとにいくつかのメソッドを定義します。1 つは値を取得し、もう 1 つは値を取得し、もう 1 つは属性の同じ名前のインスタンス変数です。

このメソッドを使用して見ることができます

p A.instance_methods

[:x, :x=, :y, :y=, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :initialize_dup, :initialize_clone, :taint, :tainted?, :untaint, :untrust, :untrusted?,..

したがって、この属性は、クラス外でアクセス可能です。

p "#{a.x},#{a.y}"

または、対応するインスタンス変数を介してクラス内で

class A
  ...
  def attributes
    [@x,@y]
  end
  ...
end
p a.attributes   #=> [5,10]
于 2012-04-04T15:15:13.253 に答える