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

#to_s या #to_str? रूबी में स्पष्ट रूप से कास्टिंग बनाम परोक्ष रूप से जबरदस्ती प्रकार

टाइप ज़बरदस्ती एक वस्तु के प्रकार को उसके मूल्य के साथ दूसरे प्रकार में बदलना है। उदाहरण के लिए, #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 दें।


  1. रूबी में लैम्ब्डा का उपयोग करना

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

  1. रूबी में इंसर्शन सॉर्ट को समझना

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

  1. रूबी में 9 नई सुविधाएँ 2.6

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