假設中定義的屬性我有一個類A
如何打通attr_reader或attr_accessor
class A
attr_accessor :x, :y
def initialize(x,y)
@x, @y = x, y
end
end
我怎樣才能得到x
和y
屬性,不知道他們究竟是如何命名的。
E.g.
a = A.new(5,10)
a.attributes # => [5, 10]
假設中定義的屬性我有一個類A
如何打通attr_reader或attr_accessor
class A
attr_accessor :x, :y
def initialize(x,y)
@x, @y = x, y
end
end
我怎樣才能得到x
和y
屬性,不知道他們究竟是如何命名的。
E.g.
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]
當您使用attr_accessor來定義,紅寶石使用refexion的類屬性,定義了幾個方法,每種屬性聲明,一個拿到價值以及其他設置,同名的實例變量該屬性的
您可以使用
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?,..
所以這個屬性是入店,類超出這個方法,用
看210或班級通過相應的實例變量
class A
...
def attributes
[@x,@y]
end
...
end
p a.attributes #=> [5,10]
感謝您的回覆,但我詢問了一個不知道屬性名稱的情況,因爲否則它不會是DRY方法。例如,如果我決定添加額外的屬性'@ d','@ e','@ f',該怎麼辦?然後,我必須將它們添加到'attributes'方法manualy以及'initialize'中,這會導致代碼重複。 – user1179942 2012-04-05 14:17:03
在這種情況下,使用塞爾吉奧的解決方案 – pgon 2012-04-05 19:36:58
而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聲明的話,你可以做類似的事情。
我認爲這是一個更好的回答給出的問題。我只會追加到它。 無論何時添加符號作爲訪問者或寫入者,Ruby都會創建{Variable} =方法。迴應?只是確保{Variable} = name存在有效的方法。第一部分是關閉返回變量中的第一個「@」。 在OP示例中,將創建方法「x =」和「y =」,並且您使用@x; x =和@y; y = – 2014-08-14 22:39:10
來查找它們。在某些情況下,這將包括':屬性='。 :/ – XtraSimplicity 2017-11-02 08:17:49
看到這個其他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
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,但如果你只關注這樣一類(而不是一個基類,一切從繼承),那麼這應該工作。
如果你有attr_writer
S/attr_accessor
,在你的屬性定義,超過他們可以通過匹配=$
正則表達式可以很容易地檢索:
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) }
注:ATTRS將返回*所有*實例變量,而不僅僅是由'attr_accessor'公開的那些變量。 – Jonah 2015-12-30 17:26:36
@Jonah:是的,那是當時的假設。對於更精確的方法,可以參考[此答案](http://stackoverflow.com/a/34440466/125816)。 – 2015-12-30 17:47:30