अभिभावक वर्ग __init__ को कई उत्तराधिकार के साथ कॉल करना, सही तरीका क्या है?


175

कहो कि मेरे पास एक बहु विरासत परिदृश्य है:

class A(object):
    # code for A here

class B(object):
    # code for B here

class C(A, B):
    def __init__(self):
        # What's the right code to write here to ensure 
        # A.__init__ and B.__init__ get called?

वहाँ लिखने के लिए दो विशिष्ट दृष्टिकोण है Cकी __init__:

  1. (पुराना तरीका) ParentClass.__init__(self)
  2. (नए शैली) super(DerivedClass, self).__init__()

हालाँकि, किसी भी मामले में, यदि माता-पिता वर्ग ( Aऔर B) एक ही सम्मेलन का पालन नहीं करते हैं, तो कोड सही तरीके से काम नहीं करेगा (कुछ छूट सकता है, या कई बार कॉल किया जा सकता है)।

तो फिर से सही तरीका क्या है? यह कहना आसान है "बस सुसंगत रहें, एक या दूसरे का अनुसरण करें", लेकिन अगर Aया Bकिसी तीसरे पक्ष के पुस्तकालय से हैं, तो क्या होगा? क्या कोई दृष्टिकोण है जो यह सुनिश्चित कर सकता है कि सभी मूल वर्ग निर्माणकर्ताओं को बुलाया जाता है (और सही क्रम में, और केवल एक बार)?

संपादित करें: यह देखने के लिए कि मेरा क्या मतलब है, अगर मैं:

class A(object):
    def __init__(self):
        print("Entering A")
        super(A, self).__init__()
        print("Leaving A")

class B(object):
    def __init__(self):
        print("Entering B")
        super(B, self).__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self):
        print("Entering C")
        A.__init__(self)
        B.__init__(self)
        print("Leaving C")

फिर मुझे मिलता है:

Entering C
Entering A
Entering B
Leaving B
Leaving A
Entering B
Leaving B
Leaving C

ध्यान दें कि Bइनिट को दो बार कहा जाता है। यदि मैं करता हूँ:

class A(object):
    def __init__(self):
        print("Entering A")
        print("Leaving A")

class B(object):
    def __init__(self):
        print("Entering B")
        super(B, self).__init__()
        print("Leaving B")

class C(A, B):
    def __init__(self):
        print("Entering C")
        super(C, self).__init__()
        print("Leaving C")

फिर मुझे मिलता है:

Entering C
Entering A
Leaving A
Leaving C

ध्यान दें कि Bइनिट को कभी नहीं बुलाया जाता है। इसलिए ऐसा लगता है कि जब तक मैं उन कक्षाओं की इनिट्स को नहीं जानता / नियंत्रित नहीं करता ( Aऔर B) मैं जिस क्लास (मैं लिख रहा हूं C) के लिए एक सुरक्षित विकल्प नहीं बना सकता ।


जवाबों:


78

दोनों तरीके ठीक काम करते हैं। super()उप-वर्ग के लिए अधिक लचीलेपन का उपयोग करते हुए दृष्टिकोण ।

प्रत्यक्ष कॉल दृष्टिकोण में, C.__init__दोनों को कॉल कर सकते हैं A.__init__और B.__init__

उपयोग करते समय super(), कक्षाओं को सहकारी एकाधिक वंशानुक्रम के लिए डिज़ाइन किया जाना चाहिए जहां Cकॉल होती है super, जो Aकोड को superआमंत्रित करता है जो कॉल भी करेगा जो कोड को आमंत्रित करता है BHttp://rhettinger.wordpress.com/2011/05/26/super-considered-super पर देखें कि इसके साथ क्या किया जा सकता है super

[बाद में संपादित के रूप में प्रतिक्रिया प्रश्न]

इसलिए ऐसा लगता है कि जब तक मैं (ए और बी) से प्राप्त होने वाली कक्षाओं की इनिट्स को नहीं जानता / नियंत्रित नहीं करता हूं, तब तक मैं उस कक्षा के लिए एक सुरक्षित विकल्प नहीं बना सकता जो मैं लिख रहा हूं (सी)।

संदर्भित लेख से पता चलता है कि कैसे एक रैपर क्लास को जोड़कर Aऔर इस स्थिति को संभालना है B। "गैर-सहकारी वर्ग को कैसे शामिल किया जाए" शीर्षक से अनुभाग में काम किया गया उदाहरण है।

एक इच्छा हो सकती है कि कई विरासत आसान थे, जिससे आप फ्लाइंगकर पाने के लिए कार और हवाई जहाज की कक्षाओं को आसानी से बना सकते हैं, लेकिन वास्तविकता यह है कि अलग-अलग डिज़ाइन किए गए घटकों को अक्सर सीमलेस रूप से फिटिंग करने से पहले एडेप्टर या रैपर की आवश्यकता होती है जैसा कि हम चाहेंगे :-)

एक अन्य विचार: यदि आप कई वंशानुक्रम का उपयोग करके कार्यक्षमता की रचना करने से नाखुश हैं, तो आप पूर्ण नियंत्रण के लिए रचना का उपयोग कर सकते हैं कि किन अवसरों पर किन तरीकों से कॉल किया जाता है।


4
नहीं, वे नहीं करते। यदि B का init सुपर नहीं कहता है, तो यदि हम super().__init__()दृष्टिकोण करते हैं तो B का init नहीं कहा जाएगा । अगर मैं फोन करता हूं A.__init__()और B.__init__()सीधे करता हूं , तो (अगर ए और बी कॉल करते हैं super) मुझे कई बार बी का इनिट कहा जा रहा है।
एडम पार्किन

3
@AdamParkin (संपादित किए गए आपके प्रश्न के बारे में): यदि किसी मूल वर्ग को सुपर () के साथ उपयोग के लिए डिज़ाइन नहीं किया गया है , तो इसे आमतौर पर सुपर कॉल में जोड़ा जा सकता है । संदर्भित लेख "गैर-सहकारी वर्ग को कैसे शामिल करें" शीर्षक वाले अनुभाग में काम किया गया उदाहरण दिखाता है।
रेमंड हेटिंगर

1
किसी तरह मैं उस खंड को याद करने में कामयाब रहा जब मैंने लेख पढ़ा। बिल्कुल वही, जिसकी मुझे तलाश थी। धन्यवाद!
एडम पार्किं

1
यदि आप अजगर लिख रहे हैं (उम्मीद है कि 3!) और किसी भी प्रकार की विरासत का उपयोग कर रहे हैं, लेकिन विशेष रूप से कई, तो rhettinger.wordpress.com/2011/05/26/super-considered-super को पढ़ने की आवश्यकता होनी चाहिए।
शॉन मेहान

1
अपवोटिंग क्योंकि हम अंत में जानते हैं कि हमारे पास फ्लाइंग कार क्यों नहीं है जब हमें यकीन था कि अब हमारे पास होगा।
15

66

आपके प्रश्न का उत्तर एक बहुत ही महत्वपूर्ण पहलू पर निर्भर करता है: क्या आपके आधार वर्ग कई विरासत के लिए डिज़ाइन किए गए हैं?

3 अलग-अलग परिदृश्य हैं:

  1. बेस क्लास असंबंधित, स्टैंडअलोन कक्षाएं हैं।

    यदि आपकी आधार कक्षाएं अलग-अलग इकाइयाँ हैं जो स्वतंत्र रूप से कार्य करने में सक्षम हैं और वे एक-दूसरे को नहीं जानते हैं, तो वे कई उत्तराधिकार के लिए डिज़ाइन नहीं किए गए हैं। उदाहरण:

    class Foo:
        def __init__(self):
            self.foo = 'foo'
    
    class Bar:
        def __init__(self, bar):
            self.bar = bar

    महत्वपूर्ण: सूचना है कि न तो Fooहै और न ही Barकॉल super().__init__()! यही कारण है कि आपका कोड सही तरीके से काम नहीं कर पाया। जिस तरह से हीरे की विरासत विरासत में काम करती है, ऐसे वर्ग जिनके आधार वर्ग को objectकॉल नहीं करना चाहिएsuper().__init__() । जैसा कि आपने देखा है, ऐसा करने से एकाधिक वंशानुक्रम टूट जाएगा क्योंकि आप अंत में किसी अन्य वर्ग के __init__बजाय कॉल कर रहे हैं object.__init__()( अस्वीकरण: बचना super().__init__()में object-subclasses मेरी निजी सिफारिश है और किसी भी तरह से एक सहमति-प्राप्त अजगर समुदाय में आम सहमति कुछ लोगों को उपयोग करने के लिए पसंद करते हैं। superउनका तर्क है कि आप हमेशा एक लिख सकते हैं, हर कक्षा में अनुकूलक अगर वर्ग के रूप में व्यवहार नहीं कर रहा है तुम आशा करते हो।)

    इसका मतलब यह भी है कि आपको कभी भी ऐसा वर्ग नहीं लिखना चाहिए जो विरासत में मिला हो objectऔर जिसमें कोई __init__विधि न हो । __init__कॉलिंग के रूप में एक विधि को परिभाषित नहीं करने का एक ही प्रभाव है super().__init__()। यदि आपकी कक्षा सीधे से विरासत में मिली है object, तो खाली कंस्ट्रक्टर को जोड़ना सुनिश्चित करें:

    class Base(object):
        def __init__(self):
            pass

    वैसे भी, इस स्थिति में, आपको प्रत्येक पैरेंट कंस्ट्रक्टर को मैन्युअल रूप से कॉल करना होगा। इसे करने के दो तरीके हैं:

    • के बिना super

      class FooBar(Foo, Bar):
          def __init__(self, bar='bar'):
              Foo.__init__(self)  # explicit calls without super
              Bar.__init__(self, bar)
    • साथ में super

      class FooBar(Foo, Bar):
          def __init__(self, bar='bar'):
              super().__init__()  # this calls all constructors up to Foo
              super(Foo, self).__init__(bar)  # this calls all constructors after Foo up
                                              # to Bar

    इन दो तरीकों में से प्रत्येक के अपने फायदे और नुकसान हैं। यदि आप उपयोग करते हैं super, तो आपकी कक्षा निर्भरता इंजेक्शन का समर्थन करेगी । दूसरी ओर, गलतियाँ करना आसान है। उदाहरण के लिए यदि आप ( Fooऔर ) के क्रम को बदलते हैं, तो आपको मेल करने के लिए कॉल को अपडेट करना होगा । इसके बिना आपको इस बारे में चिंता करने की ज़रूरत नहीं है, और कोड बहुत अधिक पठनीय है।Barclass FooBar(Bar, Foo)supersuper

  2. वर्गों में से एक मिश्रण है।

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

    उदाहरण:

    class FooMixin:
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)  # forwards all unused arguments
            self.foo = 'foo'
    
    class Bar:
        def __init__(self, bar):
            self.bar = bar
    
    class FooBar(FooMixin, Bar):
        def __init__(self, bar='bar'):
            super().__init__(bar)  # a single call is enough to invoke
                                   # all parent constructors
    
            # NOTE: `FooMixin.__init__(self, bar)` would also work, but isn't
            # recommended because we don't want to hard-code the parent class.

    यहाँ महत्वपूर्ण विवरण हैं:

    • मिक्सिन कॉल super().__init__()और किसी भी तर्क के माध्यम से इसे प्राप्त करता है।
    • Mixin से उपवर्ग inherits पहले : class FooBar(FooMixin, Bar)। यदि आधार वर्गों का क्रम गलत है, तो मिक्सिन के निर्माता को कभी नहीं बुलाया जाएगा।
  3. सभी बेस कक्षाएं सहकारी विरासत के लिए डिज़ाइन की गई हैं।

    सहकारी विरासत के लिए डिज़ाइन की गई कक्षाएं मिक्सिन की तरह हैं: वे अगली कक्षा के लिए सभी अप्रयुक्त तर्कों से गुजरती हैं। पहले की तरह, हमें अभी कॉल करना है super().__init__()और सभी पैरेंट कंस्ट्रक्टर को चेन-कॉल किया जाएगा।

    उदाहरण:

    class CoopFoo:
        def __init__(self, **kwargs):
            super().__init__(**kwargs)  # forwards all unused arguments
            self.foo = 'foo'
    
    class CoopBar:
        def __init__(self, bar, **kwargs):
            super().__init__(**kwargs)  # forwards all unused arguments
            self.bar = bar
    
    class CoopFooBar(CoopFoo, CoopBar):
        def __init__(self, bar='bar'):
            super().__init__(bar=bar)  # pass all arguments on as keyword
                                       # arguments to avoid problems with
                                       # positional arguments and the order
                                       # of the parent classes

    इस मामले में, मूल वर्गों का क्रम मायने नहीं रखता है। हम CoopBarपहले से ही इनहेरिट कर सकते हैं , और कोड अभी भी उसी तरह काम करेगा। लेकिन यह केवल सच है क्योंकि सभी तर्क कीवर्ड तर्क के रूप में पारित किए जाते हैं। स्थिति संबंधी तर्कों का उपयोग करने से तर्कों के क्रम को गलत करना आसान हो जाएगा, इसलिए सहकारी समितियों के लिए केवल तर्कों को स्वीकार करना प्रथागत है।

    यह उस नियम का भी अपवाद है जिसका मैंने पहले उल्लेख किया था: दोनों CoopFooऔर CoopBarविरासत से object, लेकिन वे अभी भी कॉल करते हैं super().__init__()। यदि वे नहीं करते हैं, तो कोई सहकारी विरासत नहीं होगी।

नीचे पंक्ति: सही कार्यान्वयन उन वर्गों पर निर्भर करता है, जिनसे आप विरासत में प्राप्त कर रहे हैं।

कंस्ट्रक्टर एक वर्ग के सार्वजनिक इंटरफ़ेस का हिस्सा है। यदि वर्ग को मिक्सिन के रूप में या सहकारी विरासत के लिए डिज़ाइन किया गया है, तो उसे प्रलेखित किया जाना चाहिए। यदि डॉक्स किसी भी प्रकार का उल्लेख नहीं करते हैं, तो यह मान लेना सुरक्षित है कि वर्ग सहकारी बहु विरासत के लिए नहीं बनाया गया है।


2
आपके दूसरे बिंदु ने मुझे उड़ा दिया। मैंने केवल मिक्सिन्स को वास्तविक सुपर क्लास के दाईं ओर देखा था और सोचा था कि वे बहुत ढीले और खतरनाक थे, क्योंकि आप यह नहीं देख सकते हैं कि जिस क्लास में आप मिश्रण कर रहे हैं उसमें वे विशेषताएँ हैं जिनकी आप उम्मीद कर रहे हैं। मैंने कभी भी मिश्रण में एक सामान्य डालने super().__init__(*args, **kwargs)और इसे पहले लिखने के बारे में नहीं सोचा था । यह काफी हद तक सही है।
Minix

10

या तो दृष्टिकोण ("नई शैली" या "पुरानी शैली") काम करेगा यदि आपके पास स्रोत कोड पर नियंत्रण है AऔरB । अन्यथा, एडेप्टर वर्ग का उपयोग आवश्यक हो सकता है।

स्रोत कोड सुलभ: "नई शैली" का सही उपयोग

class A(object):
    def __init__(self):
        print("-> A")
        super(A, self).__init__()
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        super(B, self).__init__()
        print("<- B")

class C(A, B):
    def __init__(self):
        print("-> C")
        # Use super here, instead of explicit calls to __init__
        super(C, self).__init__()
        print("<- C")
>>> C()
-> C
-> A
-> B
<- B
<- A
<- C

यहाँ, विधि रिज़ॉल्यूशन ऑर्डर (MRO) निम्नलिखित को निर्धारित करता है:

  • C(A, B)Aपहले हुक्म देता है , फिर B। MRO है C -> A -> B -> object
  • super(A, self).__init__()में शुरू की गई एमआरओ श्रृंखला के साथ जारी C.__init__है B.__init__
  • super(B, self).__init__()में शुरू की गई एमआरओ श्रृंखला के साथ जारी C.__init__है object.__init__

आप कह सकते हैं कि यह मामला कई उत्तराधिकारियों के लिए बनाया गया है

स्रोत कोड सुलभ: "पुरानी शैली" का सही उपयोग

class A(object):
    def __init__(self):
        print("-> A")
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        # Don't use super here.
        print("<- B")

class C(A, B):
    def __init__(self):
        print("-> C")
        A.__init__(self)
        B.__init__(self)
        print("<- C")
>>> C()
-> C
-> A
<- A
-> B
<- B
<- C

यहां, एमआरओ कोई फर्क नहीं पड़ता, क्योंकि A.__init__और B.__init__स्पष्ट रूप से कहा जाता है। class C(B, A):बस के रूप में अच्छी तरह से काम करेगा।

यद्यपि यह मामला नई शैली में कई विरासत के लिए "डिज़ाइन" नहीं किया गया है क्योंकि पिछले एक था, कई विरासत अभी भी संभव है।


अब, क्या होगा अगर Aऔर Bतीसरे पक्ष के पुस्तकालय से हैं - यानी, आपके पास स्रोत कोड पर कोई नियंत्रण नहीं है AऔरB ? संक्षिप्त उत्तर: आपको एक एडेप्टर वर्ग डिज़ाइन करना होगा जो आवश्यक superकॉलों को लागू करता है , फिर एमआरओ को परिभाषित करने के लिए एक खाली वर्ग का उपयोग करें (देखें रेमंड हेटिंगर का लेखsuper - विशेष रूप से अनुभाग, "गैर-सहकारी वर्ग कैसे शामिल करें")।

तीसरे पक्ष के माता-पिता: Aलागू नहीं होता है super; Bकर देता है

class A(object):
    def __init__(self):
        print("-> A")
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        super(B, self).__init__()
        print("<- B")

class Adapter(object):
    def __init__(self):
        print("-> C")
        A.__init__(self)
        super(Adapter, self).__init__()
        print("<- C")

class C(Adapter, B):
    pass
>>> C()
-> C
-> A
<- A
-> B
<- B
<- C

क्लास Adapterइम्प्लीमेंट करता है superताकि Cएमआरओ को परिभाषित कर सके, जो super(Adapter, self).__init__()निष्पादित होने पर खेलने में आता है।

और क्या होगा अगर यह चारों ओर दूसरा रास्ता है?

तीसरे पक्ष के माता-पिता: Aऔजार super; Bनहीं करता

class A(object):
    def __init__(self):
        print("-> A")
        super(A, self).__init__()
        print("<- A")

class B(object):
    def __init__(self):
        print("-> B")
        print("<- B")

class Adapter(object):
    def __init__(self):
        print("-> C")
        super(Adapter, self).__init__()
        B.__init__(self)
        print("<- C")

class C(Adapter, A):
    pass
>>> C()
-> C
-> A
<- A
-> B
<- B
<- C

निष्पादन के क्रम को छोड़कर यहां एक ही पैटर्न Adapter.__init__; superपहले कॉल करें, फिर स्पष्ट कॉल करें। ध्यान दें कि तीसरे पक्ष के माता-पिता के साथ प्रत्येक मामले में एक अद्वितीय एडाप्टर वर्ग की आवश्यकता होती है।

इसलिए ऐसा लगता है कि जब तक मैं उन कक्षाओं की इनिट्स को नहीं जानता / नियंत्रित नहीं करता ( Aऔर B) मैं जिस क्लास (मैं लिख रहा हूं C) के लिए एक सुरक्षित विकल्प नहीं बना सकता ।

यद्यपि आप उन मामलों को संभाल सकते हैं जहां आप स्रोत कोड को नियंत्रित नहीं करते हैं Aऔर Bएडेप्टर वर्ग का उपयोग करके, यह सच है कि आपको यह पता होना चाहिए कि ऐसा करने के लिए पैरेंट क्लासेस का init कैसे लागू होता है super(यदि सभी में)।


4

रेमंड के रूप में अपने जवाब में कहा, के लिए एक सीधा कॉल A.__init__और B.__init__ठीक काम करता है, और अपने कोड से पढ़े जा सकेंगे।

हालांकि, यह Cउन वर्गों के बीच विरासत लिंक का उपयोग नहीं करता है । उस लिंक को उजागर करने से आपको अधिक संगति मिलती है और अंततोगत्वा रिफ्लैक्टरिंग को आसान और कम त्रुटि वाला बनाता है। कैसे करना है इसका एक उदाहरण:

class C(A, B):
    def __init__(self):
        print("entering c")
        for base_class in C.__bases__:  # (A, B)
             base_class.__init__(self)
        print("leaving c")

1
सबसे अच्छा जवाब imho। यह विशेष रूप से उपयोगी पाया गया क्योंकि यह भविष्य में अधिक उपयोगी है
स्टीफन एलवुड

3

यह लेख सहकारी बहु विरासत को समझाने में मदद करता है:

http://www.artima.com/weblogs/viewpost.jsp?thread=281127

इसमें उस उपयोगी विधि का उल्लेख किया गया है mro()जो आपको विधि समाधान क्रम दिखाता है। आपके दूसरे उदाहरण में, जहाँ आप कॉल superकरते हैं A, superकॉल MRO में जारी रहती है। आदेश में अगली कक्षा है B, यही कारण है कि Bपहली बार में इनिट को कहा जाता है।

यहाँ आधिकारिक अजगर साइट से एक अधिक तकनीकी लेख है:

http://www.python.org/download/releases/2.3/mro/


2

यदि आप थर्ड पार्टी लाइब्रेरी से सब-क्लासिंग क्लास गुणा कर रहे हैं, तो नहीं, बेस क्लास __init__तरीकों (या किसी भी अन्य तरीकों) को कॉल करने के लिए कोई अंधा दृष्टिकोण नहीं है जो वास्तव में बेस क्लास प्रोग्राम किए जाने की परवाह किए बिना काम करता है।

superजटिल बहु विरासत वाले पेड़ों के हिस्से के रूप में सहकारी तरीकों को लागू करने के लिए डिज़ाइन की गई कक्षाओं को लिखना संभव बनाता है जो कि वर्ग लेखक को नहीं पता होना चाहिए। लेकिन इसका उपयोग करने का कोई तरीका नहीं है कि इसे मनमाने ढंग से उन वर्गों से सही रूप से प्राप्त किया जा सके जो उपयोग नहीं कर सकते हैं super

अनिवार्य रूप से, क्या किसी वर्ग को superआधार वर्ग के लिए प्रत्यक्ष कॉल के साथ या उप-वर्ग के लिए डिज़ाइन किया गया है, यह एक संपत्ति है जो वर्ग के "सार्वजनिक इंटरफ़ेस" का हिस्सा है, और इसे इस तरह से प्रलेखित किया जाना चाहिए। यदि आप उस तरीके से तृतीय-पक्ष पुस्तकालयों का उपयोग कर रहे हैं, जो पुस्तकालय लेखक से अपेक्षित है और पुस्तकालय में उचित प्रलेखन है, तो यह सामान्य रूप से आपको बताएगा कि आपको विशेष चीजों को उप-वर्ग करने के लिए क्या करना आवश्यक है। यदि नहीं, तो आपको उन कक्षाओं के स्रोत कोड को देखना होगा जिन्हें आप उप-वर्गीकृत कर रहे हैं और देखें कि उनका आधार-वर्ग-आह्वान सम्मेलन क्या है। आप एक तरीका है कि पुस्तकालय लेखकों में एक या अधिक तृतीय-पक्ष लाइब्रेरी से कई वर्गों के संयोजन कर रहे हैं नहीं किया उम्मीद है, तो यह संभव लगातार आह्वान सुपर वर्ग तरीकों को हो सकता है सब पर; यदि क्लास ए का उपयोग करना पदानुक्रम का हिस्सा है superऔर वर्ग बी एक पदानुक्रम का हिस्सा है जो सुपर का उपयोग नहीं करता है, तो न तो विकल्प काम करने की गारंटी है। आपको एक रणनीति का पता लगाना होगा जो प्रत्येक विशेष मामले के लिए काम करता है।


@RaymondHettinger ठीक है, आपने पहले ही अपने लेख में उस लेख के बारे में कुछ विचारों के साथ लिखा और जुड़ा हुआ है, इसलिए मुझे नहीं लगता कि मुझे इसमें कुछ जोड़ना है। :) मुझे नहीं लगता कि किसी भी गैर-सुपर-उपयोग करने वाले वर्ग को एक सुपर-पदानुक्रम में उदारतापूर्वक अनुकूलित करना संभव है; आपको इसमें शामिल विशेष वर्गों के अनुरूप समाधान के साथ आना होगा।
बेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.