クラス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]
内省を使って、ルーク!
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]
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を使用して宣言したい場合は、同様のことができます。
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つのクラスに対してのみこれを行うことに関心がある場合、これは機能するはずです。
この他の Stack Overflow Question を参照してください。それらはattr_accessor
。
def self.attr_accessor(*vars)
@attributes ||= []
@attributes.concat vars
super(*vars)
end
def self.attributes
@attributes
end
def attributes
self.class.attributes
end
属性にattr_writer
s/attr_accessor
sが定義されている場合は、=$
正規表現に一致させることで簡単に取得できます。
A.instance_methods.each_with_object([]) { |key, acc| acc << key.to_s.gsub(/=$/, '') if key.match(/\w=$/) }
OR
A.instance_methods.each_with_object([]) { |key, acc| acc << key if key = key.to_s.match(/^(.*\w)=$/)&.[](1) }
attr_accessorを使用してクラスの属性を定義する場合、Ruby refexionを使用して、宣言された属性ごとにいくつかのメソッドを定義します。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]