जब यह इतना समान दिखता है, तो ईगेंसेलस स्वयं के बराबर क्यों नहीं होता है?


83

मुझे कहीं याद नहीं है, और मुझे आशा है कि आप मुझे यह समझाएंगे।

किसी वस्तु की ईजेंकलश से अलग क्यों है self.class?

class Foo
  def initialize(symbol)
    eigenclass = class << self
      self
    end
    eigenclass.class_eval do
      attr_accessor symbol
    end
  end
end

तर्क की मेरी रेलगाड़ी जो इगेंकल के साथ समानता रखती class.selfहै बल्कि सरल है:

class << selfउदाहरण के तरीकों के बजाय वर्ग विधियों को घोषित करने का एक तरीका है। यह एक शॉर्टकट है def Foo.bar

इसलिए क्लास ऑब्जेक्ट के संदर्भ में, रिटर्निंग selfसमान होना चाहिए self.class। इसका कारण यह है class << selfस्थापित करेगा selfकरने के लिए Foo.class/ विशेषताओं वर्ग तरीकों की परिभाषा के लिए।

क्या मैं सिर्फ भ्रमित हूँ? या, यह रूबी मेटा-प्रोग्रामिंग की एक डरपोक चाल है?

जवाबों:


122

class << selfवर्ग विधियों की घोषणा करने के सिर्फ एक तरीके से अधिक है (हालांकि इसका उपयोग उस तरीके से किया जा सकता है)। संभवतः आपने कुछ उपयोग देखे हैं जैसे:

class Foo
  class << self
    def a
      print "I could also have been defined as def Foo.a."
    end
  end
end

यह काम करता है, और इसके बराबर है def Foo.a, लेकिन जिस तरह से यह काम करता है वह थोड़ा सूक्ष्म है। रहस्य यह है कि self, उस संदर्भ में, उस वस्तु को संदर्भित करता है Foo, जिसका वर्ग एक अद्वितीय, अनाम उपवर्ग है Class। इस उपवर्ग को Foo' ईगेंसेलस ' कहा जाता है । इसलिए def aएक नई विधि बनाता है जिसे सामान्य पद्धति कॉल सिंटैक्स द्वारा सुलभ, इगेंकलशल्स कहा जाता aहै :।FooFoo.a

अब एक अलग उदाहरण देखते हैं:

str = "abc"
other_str = "def"

class << str
  def frob
    return self + "d"
  end
end

print str.frob # => "abcd"
print other_str.frob # => raises an exception, 'frob' is not defined on other_str

यह उदाहरण पिछले एक के समान है, हालांकि यह पहली बार में बताना मुश्किल हो सकता है। frobपरिभाषित किया गया है, Stringवर्ग पर नहीं , बल्कि strएक अद्वितीय अनाम उपवर्ग पर String। तो strएक frobविधि है, लेकिन Stringसामान्य रूप से उदाहरण नहीं है। हम स्ट्रिंग के तरीकों को भी ओवरराइड कर सकते हैं (कुछ मुश्किल परीक्षण परिदृश्यों में बहुत उपयोगी)।

अब हम आपके मूल उदाहरण को समझने के लिए सुसज्जित हैं। इनसाइड Fooइनिशियलाइज़ मेथड, selfक्लास को नहीं Foo, बल्कि कुछ विशेष उदाहरण को संदर्भित करता है Foo। इसकी ईजेनक्लस एक उपवर्ग है Foo, लेकिन यह नहीं है Foo; यह नहीं हो सकता है, या फिर दूसरे उदाहरण में हमने जो चाल देखी, वह काम नहीं कर सकती। तो अपना उदाहरण जारी रखने के लिए:

f1 = Foo.new(:weasels)
f2 = Foo.new(:monkeys)

f1.weasels = 4 # Fine
f2.monkeys = 5 # Also ok
print(f1.monkeys) # Doesn't work, f1 doesn't have a 'monkeys' method.

उम्मीद है की यह मदद करेगा।


तो फिर, प्रत्येक उदाहरण निर्मित वर्ग का एक अनाम उपवर्ग है?
रॉबर्ट के

21
प्रत्येक उदाहरण का वर्ग निर्मित वर्ग का एक अनाम उपवर्ग है। f1 का वर्ग फू का गुमनाम उपवर्ग है, फू की कक्षा कक्षा का एक अनाम उपवर्ग है।
डेविड सेलर

6
अच्छा जवाब :) बहुत से लोग इसे स्पष्ट रूप से नहीं समझते हैं जैसा कि आप करते हैं।
अश्वारोही

3
एफ 1 के वास्तविक उदाहरणों से, अवधारणात्मक रूप से, एफ 1 की ईजेंकलश कैसे अलग है। यदि F1 एकमात्र उदाहरण है जो कभी भी अपने ईजेनक्लस के तरीकों तक पहुंच प्राप्त करेगा, तो f1 और उसके ईजेनक्लस के बीच का अंतर टूटने का नहीं है?
इलाजू

1
@elju हाँ, थोड़े। वास्तव में महत्वपूर्ण अंतर "फू" और "एफ 1 के ईजेनक्लस" के बीच है; अगर आपको वह मिल गया है, तो आप शायद ठीक हैं।
डेविड सेलर

46

सबसे सरल उत्तर: ईगेंसेल्स को तत्काल नहीं किया जा सकता है।

class F
 def eigen
  class << self 
   self
  end
 end
end
F.new.eigen.new #=> TypeError: can't create instance of virtual class

इस वेबसाइट पर आपके पास केवल 1 बिंदु हो सकता है, लेकिन मैं आपको और आपकी शैली को पसंद करता हूं।
घोडागुई

सहमत w / प्रतिबंध; यह एक महान जवाब है
क्रिस्टोफर स्कॉट

3
यह एक अत्यंत व्यावहारिक और उपयोगी टिप्पणी है IFF एक पहले ही ऊपर डेविड डेविडलर का उत्तर पढ़ चुका है।
जाज

यहाँ थियो पावर उस अपवाद को डेमो करता है जो उठाया जाता है।
न्यू अलेक्जेंड्रिया

11

येहुदा काट्ज़ ने " रूबी में मेटाप्रोग्रामिंग: इन ऑल अबाउट द सेल्फ " के बारे में सूक्ष्मता को समझाने का एक बहुत अच्छा काम किया है


7
उपशीर्षक या ... सूक्ष्मता? ;)
अश्वारोही

doh :) कि अभी तय करने के लिए धन्यवाद।
पीट हॉजसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.