रूबी का बढ़ा हुआ सिंटैक्स आपको उस प्रकार की त्रुटि को निर्दिष्ट करने के लिए कुछ विकल्प देता है जिसे आप उठाना चाहते हैं। नीचे दिए गए कोड में, मैंने रनटाइम त्रुटि को बढ़ाने के तीन तरीके दिखाए हैं।
raise "hello"
raise RuntimeError, "hello"
raise RuntimeError.new("hello")
# ...all of the above result in "RuntimeError: hello"
यह अच्छा है, लेकिन क्या होता है जब मैं अपवाद के अलावा कुछ और उठाना चाहता हूं? क्या होगा अगर मैं एक संख्या बढ़ाना चाहता हूँ? खैर, रूबी मुझे नहीं जाने देगी। मुझे इस तरह एक त्रुटि संदेश मिलेगा:
raise 1
# TypeError: exception class/object expected
अब यह संदेश आपको यह विश्वास करने के लिए प्रेरित कर सकता है कि एक पैरामीटर के रूप में अपवाद वर्ग/वस्तु की अपेक्षा करता है। लेकिन यह गलत है!
exception
का परिचय विधि
अगर आप raise foo
. करते हैं उठाने की विधि फू को अपवाद वस्तु होने की उम्मीद नहीं करती है। यह उम्मीद करता है कि जब भी वह foo.exception
calls कॉल करेगा तो उसे एक अपवाद वस्तु मिलेगी ।
याद रखने वाली बात यह है कि आप उठाने के लिए कुछ भी पास कर सकते हैं, जब तक कि इसमें अपवाद नामक एक विधि है जो अपवाद देता है।
इसलिए, यदि आप चाहते हैं, तो आप रूबी की संख्या कक्षाओं को बंद कर सकते हैं ताकि आप एक संख्या बढ़ा सकें। यह ऐसा दिखाई दे सकता है:
class Fixnum
def exception
RuntimeError.new("I'm number: #{ self }")
end
end
raise 42
# ...results in raise_number.rb:7:in `<main>': I'm number: 42 (RuntimeError)
यह एक साफ-सुथरी पार्टी ट्रिक है, लेकिन क्या यह वास्तविक जीवन में कभी उपयोगी हो सकती है? इस तकनीक के लिए जो मुख्य व्यावहारिक अनुप्रयोग मैं देखता हूं वह तर्क से अपवाद बनाने के लिए आवश्यक तर्क को अलग करना है जो अपवाद को बढ़ाने का निर्णय लेता है। यह निश्चित रूप से एक किनारे का मामला है। लेकिन देखते हैं कि यह कैसा दिख सकता है।
संभवतः व्यावहारिक उदाहरण
मान लीजिए कि मैं किसी प्रकार के आईओ से डेटा की एक पंक्ति पढ़ना चाहता हूं। यह नेटवर्क आईओ हो सकता है, यह एक फाइल हो सकता है। यह वास्तव में कोई फर्क नहीं पड़ता। मैं सिर्फ डेटा पढ़ना चाहता हूं और देखना चाहता हूं कि यह मान्य है या नहीं।
यदि मेरे द्वारा पढ़ा गया डेटा मान्य नहीं है, तो मैं एक अपवाद उठाना चाहता हूं। लेकिन अपवाद को इनपुट के अनुरूप बनाने की जरूरत है। नेटवर्क कनेक्शन के लिए स्थानीय फ़ाइल की तुलना में अलग डीबग जानकारी होनी चाहिए। मैं प्रत्येक प्रकार के इनपुट वर्ग के लिए कस्टम अपवाद विधियां प्रदान करके ऐसा कर सकता हूं। यहाँ कुछ छद्म माणिक दिखा रहा है कि यह कैसा दिख सकता है।
# These three classes represent different kinds of IO with different exceptions.
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"
# We raise the item, which causes the appropriate exception class to be used.
raise item
end
end
end
read_all(NetworkConnection.new(url: "example.com"), LocalFile.new("/something"), UnixPipe.new)