Ruby का raise सिंटैक्स आपको उस त्रुटि के प्रकार को निर्दिष्ट करने के लिए कुछ विकल्प देता है जिसे आप उठाना चाहते हैं। नीचे दिए गए कोड में, मैंने RuntimeError उठाने के तीन तरीके दिखाए हैं।
raise "hello" raise RuntimeError, "hello" raise RuntimeError.new("hello") # ...उपरोक्त सभी का परिणाम "RuntimeError: hello" होता है
यह अच्छा है, लेकिन क्या होता है जब मैं अपवाद के अलावा कुछ और उठाना चाहता हूँ? क्या होगा यदि मैं एक संख्या उठाना चाहता हूँ? खैर, Ruby मुझे ऐसा नहीं करने देगा। मुझे इस तरह का एक त्रुटि संदेश मिलेगा:
raise 1 # TypeError: exception class/object expected
अब यह संदेश आपको यह विश्वास दिला सकता है कि raise एक अपवाद क्लास/ऑब्जेक्ट को पैरामीटर के रूप में अपेक्षा करता है। लेकिन यह गलत है!
exception मेथड का परिचय
यदि आप `raise foo` करते हैं तो raise मेथड foo के अपवाद ऑब्जेक्ट होने की अपेक्षा नहीं करता। यह अपेक्षा करता है कि जब भी यह `foo.exception` कॉल करेगा तो उसे एक अपवाद ऑब्जेक्ट मिलेगा।
याद रखने वाली बात यह है कि आप raise को **कुछ भी** पास कर सकते हैं, बस जब तक इसमें एक `exception` नामक मेथड है जो एक अपवाद लौटाता है।
तो, यदि आप चाहते थे, तो आप Ruby के नंबर क्लासेस को मंकी-पैच कर सकते हैं ताकि आप एक संख्या उठा सकें। यहाँ देखें कि यह कैसा दिख सकता है:
class Fixnum def exception RuntimeError.new("I'm number: #{ self }") end end raise 42 # ...परिणाम raise_number.rb:7:in `<main>': I'm number: 42 (RuntimeError)
यह एक साफ-सुथरी पार्टी ट्रिक है, लेकिन क्या यह वास्तविक जीवन में कभी उपयोगी हो सकती है? इस तकनीक के लिए मुझे जो मुख्य व्यावहारिक अनुप्रयोग दिखता है वह अपवाद बनाने के लिए आवश्यक तर्क को उस तर्क से अलग करना है जो अपवाद को उठाने का फैसला करता है। यह निश्चित रूप से एक एज केस है। लेकिन आइए देखें कि यह कैसा दिख सकता है।
एक संभावित व्यावहारिक उदाहरण
मान लीजिए मैं किसी प्रकार के IO से डेटा की एक लाइन पढ़ना चाहता हूँ। यह नेटवर्क IO हो सकता है, यह एक फ़ाइल हो सकती है। यह वास्तव में मायने नहीं रखता। मैं बस डेटा पढ़ना चाहता हूँ और देखना चाहता हूँ कि यह वैध है या नहीं।
यदि मैं जो डेटा पढ़ता हूँ वह वैध नहीं है, तो मैं एक अपवाद उठाना चाहता हूँ। लेकिन अपवाद को इनपुट के अनुरूप बनाया जाना चाहिए। एक नेटवर्क कनेक्शन को स्थानीय फ़ाइल की तुलना में अलग डिबग जानकारी की आवश्यकता होती है। मैं प्रत्येक प्रकार के इनपुट क्लास के लिए कस्टम अपवाद मेथड प्रदान करके ऐसा कर सकता हूँ। यहाँ कुछ छद्म-Ruby दिखा रहा है कि यह कैसा दिख सकता है।
# ये तीन क्लासेस अलग-अलग अपवादों के साथ विभिन्न प्रकार के IO का प्रतिनिधित्व करती हैं। class NetworkConnection ... def exception NetworkConnectionError.new(url: url, ...) end end class LocalFile ... def exception FileError.new(path: path, ...) end end class UnixPipe ... def exception PipeError.new(...) end end def read_all(*items) items.each do |item| if item.readline != "foo" # हम आइटम को उठाते हैं, जिससे उपयुक्त अपवाद क्लास का उपयोग होता है। raise item end end end read_all(NetworkConnection.new(url: "example.com"), LocalFile.new("/something"), UnixPipe.new)