Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Ruby

रूबी में एक्सप्लिसिट कास्टिंग बनाम इम्प्लिसिट कोएर्सन: #to_s, #to_str, और अधिक

टाइप कोएर्सन एक ऑब्जेक्ट के टाइप को उसके मान के साथ दूसरे टाइप में बदलना है। उदाहरण के लिए, #to_s के साथ एक Integer को String में बदलना या #to_i के साथ एक Float को Integer में बदलना। शायद कम ज्ञात #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
# असफल कोएर्सन्स
"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, हम फंक्शन से एक String ऑब्जेक्ट लौटाने के लिए कहते हैं, केवल अगर मूल टाइप भी String की तरह कार्य करता है। इस कारण से, #to_str रूबी स्टैंडर्ड लाइब्रेरी में केवल String पर लागू होता है।

रूबी इम्प्लिसिट कोएर्सन का उपयोग कैसे करती है

कोएर्सन के दौरान हम जो मांग रहे हैं उसमें अधिक सटीक होने के अलावा, इम्प्लिसिट कोएर्सन और किस लिए उपयोगी है? पता चला है कि रूबी स्वयं कई परिदृश्यों में इम्प्लिसिट कोएर्सन्स का उपयोग करती है। उदाहरण के लिए, + के साथ ऑब्जेक्ट्स को संयोजित करते समय।

name = "world!"
"Hello " + name # => "Hello world!"
# #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 टाइप को कैसे कोएर्स करना है।

# #to_str के साथ
class Name
  def to_str
    @name
  end
end
"Hello " + Name.new("world!") # => "Hello world!"

यही Arrays और #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 अधिक परिदृश्यों में उपयोग किया जाता है। हम इसका उपयोग एक Array को अलग-अलग वेरिएबल्स में डिस्ट्रक्चर करने के लिए कर सकते हैं।

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। यह parse_options मेथड में पास करने से पहले #to_hash के साथ मान को हैश में कोएर्स करता है।

class Options
  def to_hash
    # 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"

आपको केवल उन ऑब्जेक्ट्स के लिए इम्प्लिसिट कास्टिंग मेथड्स को लागू करना चाहिए जो कोएर्स किए जाने वाले टाइप की तरह कार्य करते हैं, उदाहरण के लिए आपके अपने String क्लास के लिए #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 लौटाया, जो String-टाइप का नहीं है। इसके बजाय, यह #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 पर हमें एक लाइन लिखने में संकोच न करें।

  1. Ruby में Lambdas में महारत हासिल करें: बुनियादी से उन्नत तकनीकें तक Ruby में Lambdas में महारत हासिल करें: बुनियादी से उन्नत तकनीकें तक

    ब्लॉक Ruby का इतना महत्वपूर्ण हिस्सा हैं, उनके बिना भाषा की कल्पना करना कठिन है। लेकिन लैम्ब्डा? कौन लैम्ब्डा से प्यार करता है? आप वर्षों तक बिना एक का उपयोग किए जा सकते हैं। वे लगभग एक बीते युग के अवशेष लगते हैं। ...लेकिन यह पूरी तरह सच नहीं है। लैम्ब्डा की आस्तीन में कुछ दिलचस्प तरकीबें हैं एक बार

  1. रूबी के साथ इंसर्शन सॉर्ट में महारत: एक चरण-दर-चरण गाइड रूबी के साथ इंसर्शन सॉर्ट में महारत: एक चरण-दर-चरण गाइड

    नोट: यह रूबी के साथ विभिन्न सॉर्टिंग एल्गोरिदम को लागू करने पर एक श्रृंखला का भाग 4 है। भाग 1 ने बबल सॉर्ट का पता लगाया, भाग 2 ने सिलेक्शन सॉर्ट का पता लगाया, और भाग 3 ने मर्ज सॉर्ट का पता लगाया। जैसा कि हम डेटा को सॉर्ट करने के लिए विभिन्न पद्धतियों का पता लगाना जारी रखते हैं, हम इंसर्शन सॉर्ट की

  1. Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण Ruby 2.6 में 9 प्रमुख संवर्द्धन का अन्वेषण

    Ruby का एक नया संस्करण नई सुविधाओं और प्रदर्शन सुधारों के साथ आ रहा है। क्या आप परिवर्तनों के साथ बने रहना चाहेंगे? आइए एक नज़र डालते हैं! अंतहीन रेंज (Endless Ranges) Ruby 2.5 और पुराने संस्करण पहले से ही अंतहीन रेंज का एक रूप (Float::INFINITY के साथ) का समर्थन करते हैं, लेकिन Ruby 2.6 इसे अगले स्त