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

रूबी में कक्षाएं, उदाहरण और मेटाक्लास खोलना

रूबी मैजिक के नए एपिसोड में आपका स्वागत है! इस महीने का संस्करण सभी मेटाक्लास के बारे में है, एक विषय जो दो डेवलपर्स (हाय मौड!) के बीच एक चर्चा से निकला है।

मेटाक्लास की जांच करके, हम सीखेंगे कि रूबी में क्लास और इंस्टेंस तरीके कैसे काम करते हैं। साथ ही, एक स्पष्ट "परिभाषित" पास करके एक विधि को परिभाषित करने और class << self का उपयोग करके अंतर की खोज करें या instance_eval . चलो चलें!

क्लास इंस्टेंस और इंस्टेंस मेथड्स

यह समझने के लिए कि रूबी में मेटाक्लास का उपयोग क्यों किया जाता है, हम यह जांच कर शुरू करेंगे कि इंस्टेंस- और क्लास विधियों के बीच क्या अंतर हैं।

रूबी में, एक वर्ग एक वस्तु है जो अन्य वस्तुओं को बनाने के लिए एक खाका को परिभाषित करती है। कक्षाएं परिभाषित करती हैं कि उस वर्ग के किसी भी उदाहरण पर कौन सी विधियां उपलब्ध हैं।

एक वर्ग के अंदर एक विधि को परिभाषित करना एक आवृत्ति विधि बनाता है उस वर्ग पर। उस वर्ग के भविष्य के किसी भी उदाहरण में वह विधि उपलब्ध होगी।

class User
  def initialize(name)
    @name = name
  end
 
  def name
    @name
  end
end
 
user = User.new('Thijs')
user.name # => "Thijs"

इस उदाहरण में, हम User . नामक एक वर्ग बनाते हैं , एक उदाहरण विधि . के साथ नाम #name जो उपयोगकर्ता का नाम लौटाता है। कक्षा का उपयोग करके, हम तब एक वर्ग उदाहरण . बनाते हैं और इसे user . नाम के वेरिएबल में स्टोर करें . चूंकि User User . का एक उदाहरण है वर्ग, इसमें #name . है विधि उपलब्ध है।

एक वर्ग अपनी इंस्टेंस विधियों को अपनी विधि तालिका . में संग्रहीत करता है . उस वर्ग का कोई भी उदाहरण इसकी कक्षा की विधि तालिका को संदर्भित करता है ताकि इसकी आवृत्ति विधियों तक पहुंच प्राप्त हो सके।

क्लास ऑब्जेक्ट

एक वर्ग विधि एक विधि है जिसे पहले एक उदाहरण बनाए बिना सीधे कक्षा में बुलाया जा सकता है। एक क्लास मेथड इसके नाम को self. . के साथ प्रीफ़िक्स करके बनाया जाता है इसे परिभाषित करते समय।

एक वर्ग स्वयं एक वस्तु है। एक स्थिरांक वर्ग वस्तु को संदर्भित करता है, इसलिए इस पर परिभाषित वर्ग विधियों को अनुप्रयोग में कहीं से भी बुलाया जा सकता है।

class User
  # ...
 
  def self.all
    [new("Thijs"), new("Robert"), new("Tom")]
  end
end
 
User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]

self. . के साथ परिभाषित तरीके -उपसर्ग वर्ग की विधि तालिका में नहीं जोड़े जाते हैं। इसके बजाय उन्हें कक्षा के मेटाक्लास में जोड़ा जाता है।

मेटाक्लास

एक वर्ग के अलावा, रूबी में प्रत्येक वस्तु में एक छिपा हुआ मेटाक्लास होता है। मेटाक्लास सिंगलेट हैं, जिसका अर्थ है कि वे एक ही वस्तु से संबंधित हैं। अगर आप किसी क्लास के कई इंस्टेंस बनाते हैं, तो वे एक ही क्लास शेयर करेंगे, लेकिन उनके पास अलग-अलग मेटाक्लास होंगे।

thijs, robert, tom = User.all
 
thijs.class # => User
robert.class # => User
tom.class # => User
 
thijs.singleton_class  # => #<Class:#<User:0x00007fb71a9a2cb0>>
robert.singleton_class # => #<Class:#<User:0x00007fb71a9a2c60>>
tom.singleton_class    # => #<Class:#<User:0x00007fb71a9a2c10>>

इस उदाहरण में, हम देखते हैं कि यद्यपि प्रत्येक वस्तु का वर्ग User . है , उनके सिंगलटन वर्गों में अलग-अलग ऑब्जेक्ट आईडी होते हैं, जिसका अर्थ है कि वे अलग-अलग ऑब्जेक्ट हैं।

एक मेटाक्लास तक पहुंच प्राप्त करके, रूबी मौजूदा वस्तुओं में सीधे तरीके जोड़ने की अनुमति देता है। ऐसा करने से ऑब्जेक्ट की कक्षा में कोई नया तरीका नहीं जुड़ता।

robert = User.new("Robert")
 
def robert.last_name
  "Beekman"
end
 
robert.last_name # => "Beekman"
User.new("Tom").last_name # => NoMethodError (undefined method `last_name' for #<User:0x00007fe1cb116408>)

इस उदाहरण में, हम एक #last_name जोड़ते हैं robert . में संग्रहीत उपयोगकर्ता के लिए चर। हालांकि robert User . का एक उदाहरण है , User . के किसी भी नए बनाए गए उदाहरण #last_name तक पहुंच नहीं होगी विधि, क्योंकि यह केवल robert . पर मौजूद है का मेटाक्लास।

self ?

एक विधि को परिभाषित करते समय और एक रिसीवर को पास करते समय, नई विधि को रिसीवर के मेटाक्लास में जोड़ा जाता है, बजाय इसे क्लास की मेथड टेबल में जोड़ने के।

tom = User.new("Tom")
 
def tom.last_name
  "de Bruijn"
end

ऊपर के उदाहरण में, हमने #last_name . जोड़ा है सीधे tom . पर ऑब्जेक्ट, tom . पास करके विधि को परिभाषित करते समय रिसीवर के रूप में।

क्लास मेथड्स के लिए भी यह इसी तरह काम करता है।

class User
  # ...
 
  def self.all
    [new("Thijs"), new("Robert"), new("Tom")]
  end
end

यहां, हम स्पष्ट रूप से self . पास करते हैं .all . बनाते समय एक रिसीवर के रूप में तरीका। एक वर्ग परिभाषा में, self वर्ग को संदर्भित करता है (User इस मामले में), तो .all विधि User में जुड़ जाती है का मेटाक्लास।

क्योंकि User एक स्थिरांक में संग्रहीत एक वस्तु है, जब भी हम इसका संदर्भ देते हैं, हम उसी वस्तु तक पहुँचते हैं—और उसी मेटाक्लास तक।

मेटाक्लास खोलना

हमने सीखा है कि क्लास मेथड क्लास ऑब्जेक्ट के मेटाक्लास में मेथड होते हैं। यह जानने के बाद, हम क्लास मेथड्स बनाने की कुछ अन्य तकनीकों को देखेंगे जिन्हें आपने पहले देखा होगा।

class << self

हालाँकि यह शैली से थोड़ा बाहर हो गया है, कुछ पुस्तकालय class << self . का उपयोग करते हैं वर्ग विधियों को परिभाषित करने के लिए। यह सिंटैक्स ट्रिक वर्तमान वर्ग के मेटाक्लास को खोलती है और इसके साथ सीधे इंटरैक्ट करती है।

class User
  class << self
    self # => #<Class:User>
 
    def all
      [new("Thijs"), new("Robert"), new("Tom")]
    end
  end
end
 
User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]

यह उदाहरण User.all . नामक एक वर्ग विधि बनाता है User . में एक विधि जोड़कर का मेटाक्लास। जैसा कि हमने पहले देखा था, विधि के लिए स्पष्ट रूप से एक रिसीवर पास करने के बजाय, हम self . सेट करते हैं User . के लिए User . के बजाय मेटाक्लास का मेटाक्लास स्वयं।

जैसा कि हमने पहले सीखा, स्पष्ट रिसीवर के बिना किसी भी विधि परिभाषा को वर्तमान वर्ग की एक उदाहरण विधि के रूप में जोड़ा जाता है। ब्लॉक के अंदर, वर्तमान वर्ग है User का मेटाक्लास (#<Class:User> )।

instance_eval

एक अन्य विकल्प instance_eval . का उपयोग करना है , जो एक ही काम को एक बड़े अंतर के साथ करता है। हालांकि वर्ग का मेटाक्लास ब्लॉक में परिभाषित विधियों को प्राप्त करता है, self मुख्य वर्ग का संदर्भ बना हुआ है।

class User
  instance_eval do
    self # => User
 
    def all
      [new("Thijs"), new("Robert"), new("Tom")]
    end
  end
end
 
User.all # => [#<User:0x00007fb01701efb8 @name="Thijs">, #<User:0x00007fb01701ef68 @name="Robert">, #<User:0x00007fb01701ef18 @name="Tom">]

इस उदाहरण में, हम User . पर एक उदाहरण विधि परिभाषित करते हैं पहले की तरह ही मेटाक्लास है, लेकिन self अभी भी User . की ओर इशारा करता है . हालांकि यह आमतौर पर एक ही वस्तु की ओर इशारा करता है, "डिफ़ॉल्ट परिभाषित" और self विभिन्न वस्तुओं को इंगित कर सकते हैं।

हमने क्या सीखा

हमने सीखा है कि केवल कक्षाएं ही ऐसी वस्तुएँ हैं जिनमें विधियाँ हो सकती हैं, और वह उदाहरण विधियाँ वास्तव में किसी वस्तु के मेटाक्लास पर विधियाँ हैं। हम जानते हैं कि class << self बस self को स्वैप करता है आपको मेटाक्लास पर विधियों को परिभाषित करने की अनुमति देने के लिए, और हम जानते हैं कि instance_eval ज्यादातर वही काम करता है (लेकिन self . को छुए बिना )।

यद्यपि आप स्पष्ट रूप से मेटाक्लास के साथ काम नहीं करेंगे, रूबी उन्हें हुड के नीचे बड़े पैमाने पर उपयोग करती है। जब आप किसी विधि को परिभाषित करते हैं तो क्या होता है, यह जानने से आपको यह समझने में मदद मिल सकती है कि रूबी ऐसा क्यों व्यवहार करती है (और आपको वर्ग विधियों को self. के साथ उपसर्ग क्यों करना है। )।

पढ़ने के लिए धन्यवाद। यदि आप जो पढ़ते हैं उसे पसंद करते हैं, तो आप एक ई-मेल प्राप्त करने के लिए रूबी मैजिक की सदस्यता लेना पसंद कर सकते हैं जब हम महीने में एक बार एक नया लेख प्रकाशित करते हैं।


  1. रूबी में कस्टम अपवाद

    रूबी में अपने स्वयं के अपवाद बनाना आसान है। बस इन चरणों का पालन करें: 1. एक नई कक्षा बनाएं अपवाद वर्ग हैं, जैसे रूबी में बाकी सब कुछ! एक नए प्रकार का अपवाद बनाने के लिए, बस एक ऐसा वर्ग बनाएं जो StandardError या उसके किसी बच्चे से विरासत में मिला हो। class MyError < StandardError end raise MyErr

  1. हम कक्षाएं क्यों बनाते हैं?

    मेरे पिछले लेख के बाद, हम शून्य का उपयोग क्यों करते हैं, मैंने सोचा कि इस प्रश्न को अन्य चीजों के लिए पूछना एक अच्छा विचार होगा जो हम मानते हैं। लाइक... हम बदसूरत कोड के सिर्फ एक GIGANT बूँद के बजाय कक्षाओं का उपयोग क्यों करते हैं? मौलिक स्तर पर, हम कोड और डेटा को तार्किक इकाइयों में व्यवस्थित कर

  1. काफ्का और रूबी, एक साइडकीक लवस्टोरी

    एक निरंतर बढ़ते ऑल-इन-वन एपीएम के रूप में, हम यह सुनिश्चित करने के लिए बहुत समय बिताते हैं कि ऐपसिग्नल यातायात में हमारी वृद्धि का सामना कर सकता है। आमतौर पर, हम इस बारे में बात नहीं करते कि हम यह कैसे करते हैं; हमारा ब्लॉग रूबी के हुड के तहत महान चीजों के बारे में लेखों से भरा है या अमृत के साथ पाग