ruby 如何获取通过 attr_reader 或 attr_accessor 定义的属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10006889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get attributes that were defined through attr_reader or attr_accessor
提问by user1179942
Suppose I have a class A
假设我有一堂课 A
class A
attr_accessor :x, :y
def initialize(x,y)
@x, @y = x, y
end
end
How can I get xand yattributes without knowing how exactly they were named.
在不知道它们的确切命名方式的情况下,我如何获取x和y属性。
E.g.
例如
a = A.new(5,10)
a.attributes # => [5, 10]
回答by Sergio Tulentsev
Use introspection, Luke!
使用内省,卢克!
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]
回答by Nicolas Bonnefon
While Sergio's answer helps, it will return all the instance variables, which if I understand correctly the OP's question, is not what is asked.
虽然塞尔吉奥的回答有帮助,但它会返回所有实例变量,如果我正确理解了 OP 的问题,这不是所问的问题。
If you want to return only the 'attributes' that have e.g. a mutator, you have to do something slightly more complicated such as:
如果您只想返回具有例如 mutator 的“属性”,则必须执行稍微复杂一些的操作,例如:
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
This returns only the attributes declared with attr_accessor (or with a manually created mutator), and keep the internal instance variables hidden. You can do something similar if you want the ones declared with attr_reader.
这仅返回使用 attr_accessor(或使用手动创建的修改器)声明的属性,并隐藏内部实例变量。如果你想要用 attr_reader 声明的那些,你可以做类似的事情。
回答by marksiemers
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
This may not be the DRY-est, but if you are only concerned with doing this for one class (as opposed to a base class that everything inherits from), then this should work.
这可能不是 DRY-est,但如果您只关心为一个类(而不是所有继承自的基类)执行此操作,那么这应该可行。
回答by reto
See this other Stack Overflow Question. They override attr_accessor.
请参阅其他堆栈溢出问题。他们覆盖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
回答by pgon
when you use attr_accessor to define attributes in a class, Ruby using refexion, define a couple of methods, for each attribute declared, one to get the value and other to set, an instance variable of the same name of the attribute
当你使用 attr_accessor 在类中定义属性时,Ruby 使用 refexion,定义几个方法,为每个声明的属性,一个获取值,另一个设置,属性同名的实例变量
you can see this methods using
你可以看到这个方法使用
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?,..
So this attributes are accesible, outside the class, with
所以这个属性是可访问的,在类之外,与
p "#{a.x},#{a.y}"
or inside the class through the corresponding instance variable
或者在类内部通过相应的实例变量
class A
...
def attributes
[@x,@y]
end
...
end
p a.attributes #=> [5,10]
回答by zinovyev
If you have attr_writers/attr_accessors defined on your attributes, than they can be easily retrieved by matching the =$regexp:
如果您在属性上定义了attr_writers/ attr_accessors,则可以通过匹配正则=$表达式轻松检索它们:
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) }

