2012-04-04 7 views
18

मान लीजिए के माध्यम से परिभाषित किया गया है मैं एक वर्ग Aकैसे विशेषताओं attr_reader या attr_accessor

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] 

उत्तर

24

आत्मनिरीक्षण, ल्यूक का प्रयोग करें!

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] 
+2

नोट: attrs * सभी वापस आ जाएगी * उदाहरण चर, 'attr_accessor' – Jonah

+0

@ जोनाह द्वारा उजागर किए गए लोगों की बजाय, हां, यह तब वापस धारणा थी। एक और सटीक विधि के लिए, कोई [इस उत्तर] (http://stackoverflow.com/a/34440466/125816) का संदर्भ ले सकता है। –

1

जब आप एक कक्षा में गुण, refexion का उपयोग कर रूबी को परिभाषित करने के attr_accessor उपयोग करते हैं, तरीकों की एक जोड़ी, के लिए प्रत्येक विशेषता घोषित एक मूल्य प्राप्त करने के एक ही नाम का एक उदाहरण चर को परिभाषित है, और अन्य स्थापित करने के लिए, विशेषता का

आप उपयोग कर

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] 
+3

आपकी प्रतिक्रिया के लिए धन्यवाद, लेकिन मैंने एक मामले के बारे में पूछा जब मुझे गुणों के नाम नहीं पता, क्योंकि अन्यथा यह DRY दृष्टिकोण नहीं होगा।उदाहरण के लिए, यदि मैं अतिरिक्त विशेषताओं '@ d', '@ e',' @ f' जोड़ने का निर्णय लेता हूं तो क्या होगा। फिर मुझे उन्हें 'एट्रिब्यूट्स' विधि मैनुअल के साथ-साथ 'प्रारंभिक' में जोड़ना होगा, जो कोड के दोहराव की ओर जाता है। – user1179942

+0

इस स्थिति में, सर्जीओ समाधान – pgon

12

जबकि सर्जियो के जवाब में मदद करता है के माध्यम से वर्ग के अंदर, यह सब उदाहरण चर, अगर मैं सही ढंग से ओपी के सवाल को समझने जो, क्या कहा जाता है नहीं है वापस आ जाएगी।

यदि आप केवल 'विशेषताओं' को वापस करना चाहते हैं जो उदा। एक 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 

यह केवल गुण attr_accessor (या एक मैन्युअल रूप से बनाई गई mutator के साथ) के साथ घोषित देता है, और छिपा आंतरिक उदाहरण चर रखने के लिए। यदि आप attr_reader के साथ घोषित किए गए लोगों को चाहते हैं तो आप कुछ ऐसा ही कर सकते हैं।

+0

का उपयोग करें मुझे लगता है कि यह प्रश्न दिया गया एक बेहतर जवाब है। मैं बस इसे जोड़ दूंगा। रूबी {वैरिएबल} = विधियों बनाता है जब भी एक प्रतीक या लेखक के रूप में एक प्रतीक जोड़ा गया है। का जवाब? बस यह सुनिश्चित करता है कि {वैरिएबल} = नाम के साथ एक वैध विधि मौजूद है। पहला भाग लौटा चर पर पहले "@" को बंद करना है। ओपी उदाहरण में, विधियों "x =" और "y =" बनाए जाएंगे, और आप उन्हें @x; x = और @y; y = –

+0

के साथ ढूंढ रहे हैं, कुछ मामलों में, इसमें ' गुण = '। : / – XtraSimplicity

3

यह अन्य 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 
1
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 

यह सूखी-est नहीं हो सकता है, लेकिन यदि आप केवल एक वर्ग (के रूप में एक आधार वर्ग है कि सब कुछ से विरासत के खिलाफ) के लिए यह कर को लेकर चिंतित हैं, तो यह काम करना चाहिए।

0

आप attr_writer रों है/attr_accessor रों, अपनी विशेषताएं पर परिभाषित की तुलना में वे आसानी से =$ regexp मिलान के द्वारा प्राप्त किया जा सकता है:

A.instance_methods.each_with_object([]) { |key, acc| acc << key.to_s.gsub(/=$/, '') if key.match(/\w=$/) } 

या

A.instance_methods.each_with_object([]) { |key, acc| acc << key if key = key.to_s.match(/^(.*\w)=$/)&.[](1) } 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^