2008-10-18 12 views
9

मुझे पता है कि यह डिज़ाइन द्वारा है कि आप किसी ऑब्जेक्ट को नष्ट होने पर क्या होता है इसे नियंत्रित नहीं कर सकते हैं। मैं कुछ क्लास विधि को अंतिम रूप देने के बारे में भी जानता हूं।आरएआईआई (या, रुबी में संसाधन कैसे प्रबंधित करें)

हालांकि सी ++ के आरएआईआई के लिए रूबी मुहावरे (संसाधन कन्स्ट्रक्टर में शुरू किए गए हैं, विनाशक में बंद हैं)? त्रुटियों या अपवाद होने पर भी लोग वस्तुओं के अंदर उपयोग किए जाने वाले संसाधनों का प्रबंधन कैसे करते हैं?

सुनिश्चित काम करता है का उपयोग करना:

f = File.open("testfile") 
begin 
    # .. process 
rescue 
    # .. handle error 
ensure 
    f.close unless f.nil? 
end 

लेकिन वर्ग के उपयोगकर्ताओं पूरे शुरू-बचाव-सुनिश्चित चाचा हर खुला विधि कॉल किया जाना चाहिए करने के लिए याद करने के लिए किया है।

उदाहरण के लिए, मैं निम्नलिखित वर्ग होगा:

class SomeResource 
def initialize(connection_string) 
    @resource_handle = ...some mojo here... 
end 

def do_something() 
    begin 
    @resource_handle.do_that() 
    ... 
    rescue 
    ... 
    ensure 
end 

def close 
    @resource_handle.close 
end 

end 

resource_handle यदि अपवाद कुछ अन्य वर्ग द्वारा कारण है और स्क्रिप्ट बाहर निकल जाता है बंद कर दिया नहीं किया जाएगा।

या समस्या है कि मैं अभी भी यह भी कर रहा हूं सी ++ - जैसे?

उत्तर

15

तो है कि उपयोगकर्ताओं को भी नहीं "करने के लिए याद करने के लिए है पूरे शुरू-बचाव-सुनिश्चित चाचा" yield साथ rescue/ensure गठबंधन।

class SomeResource 
    ... 
    def SomeResource.use(*resource_args) 
    # create resource 
    resource = SomeResource.new(*resource_args) # pass args direct to constructor 
    # export it 
    yield resource 
    rescue 
    # known error processing 
    ... 
    ensure 
    # close up when done even if unhandled exception thrown from block 
    resource.close 
    end 
    ... 
end 

क्लाइंट कोड के रूप में उपयोग कर सकते हैं इस प्रकार है:

SomeResource.use(connection_string) do | resource | 
    resource.do_something 
    ... # whatever else 
end 
# after this point resource has been .close()d 

वास्तव में यह कैसे File.open संचालित है - सबसे अच्छे रूप में भ्रामक पहले उत्तर बनाने (अच्छी तरह से यह मेरी काम सहयोगियों लिए किया गया था)।

File.open("testfile") do |f| 
    # .. process - may include throwing exceptions 
end 
# f is guaranteed closed after this point even if exceptions are 
# thrown during processing 
-1

http://www.rubycentral.com/pickaxe/tut_exceptions.html

रूबी में देखें, तो आप एक ensure बयान का प्रयोग करेंगे:

f = File.open("testfile") 
begin 
    # .. process 
rescue 
    # .. handle error 
ensure 
    f.close unless f.nil? 
end 

यह अजगर, जावा, या के उपयोगकर्ताओं के लिए परिचित होंगे सी में # है कि यह ट्राई/कैच/अंत में की तरह काम करता ।

+3

हालांकि यह काम करता है, आपको उस व्यक्ति पर निर्भर होना चाहिए जो सही काम करने के लिए आपकी कक्षा का उपयोग कर रहा है। उन्हें पूरी तरह से शुरू करने के लिए याद रखना होगा-सुनिश्चित करें कि प्रत्येक बार खुली विधि को बुलाए जाने की चाचा सुनिश्चित करें। मैं इस स्पष्ट को बनाने के लिए प्रश्न संपादित कर रहा हूं, लेकिन उत्तर के लिए धन्यवाद :) – moogs

8

कैसे yield एक ब्लॉक के लिए संसाधन में? उदाहरण:

File.open("testfile") do |f| 
    begin 
    # .. process 
    rescue 
    # .. handle error 
    end 
end 
+0

वास्तव में, ब्लॉक # ब्लॉक के साथ बुलाया गया फ़ाइल # एक 'सुनिश्चित' ब्लॉक है, जो फ़ाइल को ठीक से बंद करता है, जो कुछ भी होता है। तो हाँ, आप ब्लॉक को सुनिश्चित/सुनिश्चित कर सकते हैं, लेकिन वे वैकल्पिक हैं। – webmat

+0

बिल्कुल। इस मुहावरे के साथ, आपको केवल संसाधनों का उपयोग करने वाले सभी कोडों के बजाय प्रति प्रकार संसाधनों को सुनिश्चित करने के लिए ब्लॉक को लागू करना होगा। – bk1e

2

या मैं की समस्या अधिक है अभी भी बहुत इस कर रहा हूँ सी ++ - पसंद है?

हां यह तब से है जब सी ++ संसाधन डीलोकेशन स्टैक पर सबकुछ के लिए होता है। अवांछित ढेर = संसाधन नष्ट = विनाशकों को बुलाया और वहां से चीजें जारी की जा सकती हैं। चूंकि रुबी के पास कोई विनाशक नहीं है, इसलिए ऐसा नहीं होता है जब "सबकुछ और किया जाता है" जगह से पकड़ने के संग्रह से आप जहां से हैं, कई चक्रों में देरी हो सकती है। आपके पास फाइनेंजर्स हैं लेकिन उन्हें "लिम्बो" कहा जाता है (सब कुछ उनके लिए उपलब्ध नहीं है) और उन्हें जीसी पर बुलाया जाता है।

इसलिए यदि आप कुछ संसाधनों के लिए हैंडल धारण कर रहे हैं जो बेहतर रिलीज़ हो जाए तो आपको इसे स्पष्ट रूप से रिलीज़ करने की आवश्यकता है। दरअसल इस तरह की स्थिति को संभालने के लिए सही मुहावरे

def with_shmoo 
    handle = allocate_shmoo 
    yield(handle) 
ensure 
    handle.close 
end