टाइप ज़बरदस्ती एक वस्तु के प्रकार को उसके मूल्य के साथ दूसरे प्रकार में बदलना है। उदाहरण के लिए, #to_s
. के साथ एक पूर्णांक को एक स्ट्रिंग में बदलना या #to_i
. के साथ एक पूर्णांक में फ़्लोट करें . शायद कम-ज्ञात #to_str
और #to_int
कुछ ऑब्जेक्ट लागू करने के तरीके पहली नज़र में वही करते हैं, लेकिन कुछ अंतर हैं।
ऐपसिग्नल अकादमी के इस संस्करण में, हम रूबी में स्पष्ट रूप से कास्टिंग और निहित रूप से जबरदस्ती के प्रकारों में गोता लगाएंगे, जबकि टाइपकास्टिंग अभिनेताओं पर संक्षेप में बात करेंगे। हम दोनों विधियों के बीच अंतर को कवर करेंगे, और चर्चा करेंगे कि उनका उपयोग कैसे किया जाता है।
आइए पहले देखें कि कैसे हम आम तौर पर स्पष्ट कास्टिंग हेल्पर्स के साथ रूबी में विभिन्न प्रकारों के लिए मूल्यों को बाध्य करते हैं।
स्पष्ट कास्टिंग सहायक
सबसे आम कास्टिंग सहायक हैं #to_s
, #to_i
, #to_a
और #to_h
. ये स्पष्ट कास्टिंग विधियां हैं। वे किसी मान को एक प्रकार से दूसरे प्रकार में आसानी से बदलने में हमारी सहायता करते हैं।
स्पष्ट सहायक स्पष्ट वादे के साथ आते हैं। जब भी #to_s
किसी ऑब्जेक्ट पर कॉल किया जाता है, यह हमेशा होगा एक स्ट्रिंग लौटाएं, भले ही वस्तु वास्तव में एक स्ट्रिंग में अच्छी तरह से परिवर्तित न हो। यह माइकल कीटन को बैटमैन के रूप में कास्ट करने जैसा है। आपको एक बैटमैन मिलेगा, भले ही कोई कॉमेडी अभिनेता इस भूमिका के लिए विशेष रूप से उपयुक्त न हो।
रूबी इन सहायक विधियों को रूबी मानक पुस्तकालय में लगभग किसी भी मूल वस्तु पर प्रदान करता है।
:foo.to_s # => "foo"
10.0.to_i # => 10
"10".to_i # => 10
ये तरीके, खासकर #to_s
, रूबी में सबसे बुनियादी प्रकारों पर लागू किए जाते हैं। जबकि कास्टिंग लगभग हमेशा एक मान देता है, परिणाम वह नहीं हो सकता है जिसकी हम अपेक्षा करते हैं।
"foo10".to_i # => 0
[1, 2, 3].to_s # => "[1, 2, 3]"
{ :foo => :bar }.to_s # => "{:foo=>:bar}"
{ :foo => :bar }.to_a # => [[:foo, :bar]]
Object.to_s # => "Object"
Object.new.to_s # => "#<Object:0x00007f8e6d053a90>"
#to_s
को कॉल करना , #to_i
, #to_a
और #to_h
सहायक किसी भी मूल्य को चयनित प्रकार के लिए बाध्य करता है। मूल्य के साथ क्या होता है, इस पर ध्यान दिए बिना वे उस प्रकार का प्रतिनिधित्व करते हैं जिस पर इसे मजबूर किया जाता है।
अंतर्निहित जबरदस्ती के तरीके
उन मानों पर कॉलिंग टाइप कास्टिंग विधियां जो हमारे द्वारा कास्ट किए जा रहे प्रकार की तरह कार्य नहीं करती हैं, त्रुटियों या डेटा की हानि का कारण बन सकती हैं। रूबी निहित जबरदस्ती के तरीके भी प्रदान करता है जो केवल एक मूल्य लौटाता है जब वस्तुएं प्रकार की तरह काम करती हैं। इस तरह हम यह सुनिश्चित कर सकते हैं कि मान हमारे इच्छित प्रकार की तरह कार्य करता है। ये निहित जबरदस्ती के तरीके हैं #to_str
, #to_int
, #to_ary
और #to_hash
।
निहित जबरदस्ती किसी भी भूमिका के रूप में लियोनार्ड निमोय को कास्ट करने जैसा है लेकिन स्पॉक। यदि चरित्र स्पॉक के काफी करीब है तो वे काम करेंगे, लेकिन अगर वे नहीं हैं तो असफल हो जाते हैं। #to_str
सहायक कोशिश करता है एक स्ट्रिंग में कनवर्ट करने के लिए, लेकिन एक NoMethodError
बढ़ाएगा यदि वस्तु विधि को लागू नहीं करती है और उसे परोक्ष रूप से मजबूर नहीं किया जा सकता है।
10.to_int # => 10
10.0.to_int # => 10
require "bigdecimal"
BigDecimal.new("10.0000123").to_int # => 10
# Unsuccessful coercions
"10".to_int # => NoMethodError
"foo10".to_int # => NoMethodError
[1, 2, 3].to_str # => NoMethodError
{ :foo => :bar }.to_str # => NoMethodError
{ :foo => :bar }.to_ary # => NoMethodError
Object.to_str # => NoMethodError
Object.new.to_str # => NoMethodError
हम देख सकते हैं कि रूबी अब जो करती है उसमें थोड़ी अधिक सख्त है और अनुरोधित प्रकारों के लिए बाध्य नहीं है। यदि जबरदस्ती संभव नहीं है, तो #to_*
ऑब्जेक्ट पर विधि लागू नहीं की जाती है और इसे कॉल करने से NoMethodError
उत्पन्न होता है ।
निहित जबरदस्ती का उपयोग करते समय, उदा। #to_str
, हम फ़ंक्शन को स्ट्रिंग ऑब्जेक्ट वापस करने के लिए कहते हैं, केवल तभी जब मूल प्रकार भी स्ट्रिंग की तरह कार्य करता है। इस कारण से, #to_str
केवल रूबी मानक पुस्तकालय में स्ट्रिंग पर लागू किया गया है।
रूबी किस तरह से जबरदस्ती का इस्तेमाल करती है
एक जबरदस्ती के दौरान हम जो मांग रहे हैं, उसमें अधिक सटीक होने के अलावा, निहित जबरदस्ती और क्या उपयोगी है? पता चलता है कि रूबी काफी हद तक परिदृश्यों में निहित दबावों का उपयोग करती है। उदाहरण के लिए, वस्तुओं को +
. के साथ संयोजित करते समय ।
name = "world!"
"Hello " + name # => "Hello world!"
# Without #to_str
class Name
def initialize(name)
@name = name
end
end
"Hello " + Name.new("world!") # => TypeError: no implicit conversion of Name into String
यहाँ, हम देखते हैं कि रूबी एक TypeError
उठाती है चूंकि यह Name
. से एक अंतर्निहित रूपांतरण नहीं कर सकता है String
में टाइप करें ।
अगर हम #to_str
. लागू करते हैं कक्षा में, रूबी जानता है कि Name
. के साथ जबरदस्ती कैसे की जाती है टाइप करें।
# With #to_str
class Name
def to_str
@name
end
end
"Hello " + Name.new("world!") # => "Hello world!"
एरेज़ और #to_ary
. के लिए भी यही काम करता है ।
class Options
def initialize
@internal = []
end
def <<(value)
@internal << value
end
end
options = Options.new
options << :foo
[:some_prefix] + options # => TypeError: no implicit conversion of Options into Array
class Options
def to_ary
@internal
end
end
[:some_prefix] + options # => [:some_prefix, :foo]
लेकिन #to_ary
अधिक परिदृश्यों में उपयोग किया जाता है। हम इसका उपयोग एक ऐरे को अलग-अलग चरों में नष्ट करने के लिए कर सकते हैं।
options = Options.new
options << :first
options << :second
options << :third
first, second, third = options
first # => :first
second # => :second
third # => :third
यह ऑब्जेक्ट का ब्लॉक पैरामीटर में रूपांतरण भी करता है।
[options].each do |(first, second)|
first # => :first
second # => :second
end
ऐसे और भी परिदृश्य हैं जहां निहित जबरदस्ती के तरीकों का उपयोग किया जाता है, जैसे कि #to_hash
**
के साथ . यह #to_hash
. के साथ मान को हैश में ले जाता है इसे parse_options
. पर भेजने से पहले विधि।
class Options
def to_hash
# Create a hash from the Options Array
Hash[*@internal]
end
end
def parse_options(opts)
opts
end
options = Options.new
options << :key
options << :value
parse_options(**options) # => {:key=>:value}
प्रवर्तन प्रकार
जब प्रकार अज्ञात प्रकार का होता है तो रूबी अधिक लचीला जबरदस्ती के तरीके भी प्रदान करता है और हम यह सुनिश्चित करना चाहते हैं कि हमें सही प्रकार मिले। प्रत्येक मूल प्रकार के लिए एक है (String(...)
, Integer(...)
, Float(...)
, Array(...)
, Hash(...)
, आदि)।
String(self) # => "main"
String(self.class) # => "Object"
String(123456) # => "123456"
String(nil) # => ""
Integer(123.999) # => 123
Integer("0x1b") # => 27
Integer(Time.new) # => 1204973019
Integer(nil) # => TypeError: can't convert nil into Integer
String(...)
विधि पहले #to_str
. को कॉल करने का प्रयास करती है मूल्य पर, और जब वह विफल हो जाता है, तो यह अपने #to_s
. को कॉल करता है तरीका। सभी ऑब्जेक्ट एक #to_str
परिभाषित नहीं करते हैं विधि, इसलिए दोनों निहित जबरदस्ती के साथ जाँच (#to_str
) और स्पष्ट (#to_s
) कास्टिंग विधियों से संभावना बढ़ जाती है कि स्ट्रिंग रूपांतरण काम करेगा और आपको वह मान मिलेगा जो आप चाहते हैं। पहले निहित जबरदस्ती के लिए कॉल करने से हमें एक परिणाम प्राप्त होने की अधिक संभावना होती है जिसका मूल्य समान होता है लेकिन यह ज़बरदस्त प्रकार का होता है, न कि "#<Object:0x00007f8e6d053a90>"
जैसा कुछ। ।
class MyString
def initialize(value)
@value = value
end
def to_str
@value
end
end
s = MyString.new("hello world")
s.to_s # => "#<MyString:0x...>"
s.to_str # => "hello world"
String(s) # => "hello world"
आपको केवल उन वस्तुओं के लिए निहित कास्टिंग विधियों को लागू करना चाहिए जो ज़बरदस्ती प्रकार की तरह कार्य करते हैं, उदा। #to_str
अपने स्वयं के स्ट्रिंग वर्ग के लिए।
पहले निहित जबरदस्ती की कोशिश के अलावा, String(...)
सहायक भी लौटे प्रकार की जाँच करता है। #to_str
सिर्फ एक तरीका है जो किसी भी प्रकार के मूल्य को वापस कर सकता है, यहां तक कि गैर-स्ट्रिंग भी। यह सुनिश्चित करने के लिए कि हमें अनुरोधित प्रकार का मान प्राप्त हो String(...)
एक TypeError
उठाता है यदि प्रकार मेल नहीं खाते।
class MyString
def to_str
nil
end
end
s = MyString.new("hello world")
s.to_s # => "#<MyString:0x...>"
s.to_str # => nil
String(s) # => "#<MyString:0x...>"
यहाँ, हम देख सकते हैं कि रूबी #to_str
. के परिणाम को नज़रअंदाज़ कर देती है क्योंकि यह nil
लौटा है , जो स्ट्रिंग-प्रकार का नहीं है। इसके बजाय, यह #to_s
. पर वापस आ जाता है परिणाम।
अगर #to_s
nil
भी लौटाता है और इस प्रकार सही प्रकार का नहीं है, String(...)
एक TypeError
उठाएगा ।
class MyString
def to_str
nil
end
def to_s
nil
end
end
s = MyString.new("hello world")
s.to_s # => nil
s.to_str # => nil
String(s) # => TypeError: can't convert MyString to String (MyString#to_s gives NilClass)
हालांकि वे टाइप ज़बरदस्ती लागू करने में अधिक विश्वसनीय हो सकते हैं, ध्यान दें कि कास्टिंग सहायक विधियाँ (String(...)
, Integer(...)
, आदि) आमतौर पर थोड़े धीमे होते हैं क्योंकि उन्हें दिए गए मान पर अधिक जाँच करने की आवश्यकता होती है।
निष्कर्ष में
जब आप यह सुनिश्चित करना चाहते हैं कि आप किसी वस्तु के लिए सही प्रकार के डेटा के साथ काम कर रहे हैं, तो टाइप ज़बरदस्ती एक उपयोगी प्रक्रिया है। इस पोस्ट में, हमने स्पष्ट कास्टिंग हेल्पर्स जैसे #to_s
. के बारे में अपने ज्ञान को ताज़ा किया है , #to_i
, #to_a
और #to_h
. हमने ऐसे उदाहरणों को भी देखा जब निहित सहायकों जैसे #to_str
, #to_int
, #to_ary
और #to_hash
उपयोगी हैं और रूबी द्वारा ही उनका उपयोग कैसे किया जाता है।
हमें उम्मीद है कि आपको इस प्रकार की जबरदस्ती का अवलोकन उपयोगी लगा होगा और आपने अभिनेता की टाइपकास्टिंग सादृश्यता को कैसे पाया। हमेशा की तरह, हमें बताएं कि क्या कोई ऐसा विषय है जिसे आप हमें कवर करना चाहते हैं। यदि आपके कोई प्रश्न या टिप्पणी हैं, तो बेझिझक हमें एक लाइन @AppSignal दें।