2009-04-02 28 views
12

चलो कहते हैं कि मैं एक रूबी वर्ग करते हैं: यदि मैं कोशिश करते हैं और MyClass.property=x करक्या class.property = x x के अलावा कुछ और करना संभव है?

class MyClass 
    def self.property 
    return "someVal" 
    end 

    def self.property=(newVal) 
    # do something to set "property" 
    success = true 

    return success # success is a boolean 
    end 
end 

, पूरे बयान की वापसी मान हमेशा एक्स है। यह बहुत सी सी-आधारित/प्रेरित भाषाओं में एक बूलियन "सफलता" मान वापस करने के लिए एक सम्मेलन है - क्या रूबी में "बराबर वाक्यविन्यास" का उपयोग करके एक सेटटर के लिए ऐसा करना संभव है?

इसके अलावा - यदि यह संभव नहीं है, तो क्यों नहीं? क्या "बराबर सेटटर" ऑपरेशन को एक मूल्य वापस करने की इजाजत देने के लिए कोई कल्पनीय नकारात्मक पक्ष है?

उत्तर

11

एक नकारात्मक पक्ष यह है कि आप श्रृंखलित काम अर्थ विज्ञान टूट जाएगा है:

$ irb 
irb(main):001:0> x = y = 3 
=> 3 
irb(main):002:0> p x 
3 
=> nil 
irb(main):003:0> p y 
3 
=> nil 
irb(main):004:0> 

पर विचार करें: अगर यह काम किया

x = MyClass.property = 3 

फिर xtrue ले जाएगा के रूप में आप की उम्मीद थी (राइट-संबद्धता)। यह आपके इंटरफ़ेस का उपयोग करने वाले लोगों के लिए आश्चर्यचकित हो सकता है और सामान्य अर्थशास्त्र में उपयोग किया जा सकता है।

तुम भी मिला मुझे, समानांतर काम के बारे में सोच जैसे:

x, y = 1, 2 

जाहिर है कि अभिव्यक्ति से वापसी मान implementation specific है ... मुझे लगता है मैं समानांतर कार्य :)

चेनिंग नहीं की जाएगी अच्छा प्रश्न!

+0

मैं पहली बार के रूप में "यह पढ़ अगर आप इस तरह एक्सेसर परिभाषित, आप श्रृंखलित काम अर्थ विज्ञान टूट जाएगा "। चूंकि रैंपियन का जवाब स्पष्ट हो जाता है, यह मामला नहीं है: एक आकलन विधि का वापसी मूल्य सामान्य रूप से अनदेखा किया जाता है। मार्टिन क्या कह रहा है "भाषा आपको ऐसा करने की अनुमति नहीं देती है, अगर ऐसा होता है, तो आप जंजीर असाइनमेंट सेमेन्टिक्स तोड़ देंगे"। –

5

मैं रूबी विशेषज्ञ नहीं हूं लेकिन मैं उस मामले के लिए नहीं कहूंगा कि मुझे डर है। एक प्रॉपर्टी सेटर पूरी तरह से एक निजी क्षेत्र के मूल्य को निर्धारित करने के लिए है, न कि परिणाम कोड लौटने जैसे साइड इफेक्ट्स।

यदि आप उस कार्यक्षमता को चाहते हैं तो सेटटर को भूलें और TrySetProperty नामक एक नई विधि लिखें या जो कुछ संपत्ति सेट करने का प्रयास करता है और एक बूलियन लौटाता है।

7

मार्टिन की तरह, यह असाइनमेंट चेनिंग तोड़ देगा।

जिस तरह से रूबी असाइनमेंट विधियों को MyClass.property = 3(lambda { |v| MyClass.send('property=', v); v })[3] के समतुल्य रूप में परिभाषित किया गया है (वास्तव में नहीं, लेकिन यह दिखाता है कि कैसे चेनिंग काम करता है)। असाइनमेंट का वापसी मूल्य हमेशा असाइन किया गया मान होता है।

आप अपने MyClass#property= विधि का परिणाम देखने के लिए चाहते हैं, तो का उपयोग #send:

irb> o = Object.new 
=> #<Object:0x15270> 
irb> def o.x=(y) 
irb> @x = y+1 
irb> puts "y = #{y}, @x = #@x" 
irb> true 
irb> end 
=> nil 
irb> def o.x 
irb> puts "@x = #@x" 
irb> @x 
irb> end 
=> nil 
irb> o.x = 4 
y = 4, @x = 5 
=> 4 
irb> o.x 
@x = 5 
=> 5 
irb> o.send('x=', 3) 
y = 3, @x = 4 
=> true 

हालांकि, गहरे लाल रंग का तरीका यह है अपवादों के साथ है - कुछ काम के दौरान गलत हो जाता है, एक बढ़ा अपवाद। तब सभी invokers इसे संभाल चाहिए कुछ गलत हो जाता है, तो एक वापसी मान, जो आसानी से अनदेखा किया जा सकता विपरीत,:

# continued from above... 
irb> def o.x=(y) 
irb> unless y.respond_to? :> and (y > 0 rescue false) 
irb>  raise ArgumentError, 'new value must be > 0', caller 
irb> end 
irb> @x = y + 1 
irb> puts "y = #{y}, @x = #@x" 
irb> end 
=> nil 
irb> o.x = 4 
y = 4, @x = 5 
=> 4 
irb> o.x = 0 
ArgumentError: new value must be > 0 
    from (irb):12 
    from :0 
irb> o.x = "3" 
ArgumentError: new value must be > 0 
    from (irb):13 
    from :0 
irb> o.x 
@x = 5 
=> 5 
संबंधित मुद्दे