2012-06-28 30 views
6
scala> class A 
defined class A 

scala> trait B 
defined trait B 

वर्ग A की एक वस्तु बनाना हमें देता है:एक विशेषता में मिश्रण करते समय एक अज्ञात वर्ग क्यों बनाया जाता है?

scala> new A 
res4: A = [email protected] 

लेकिन विशेषता B में मिश्रित के साथ वर्ग A की एक वस्तु बनाने हमें देता है:

scala> new A with B 
res3: A with B = [email protected] 

यहाँ हम एक अनाम वर्ग है (anon द्वारा संकेतित)। क्यूं कर ?

ऐसा इसलिए है क्योंकि A with B टाइप को एक नया प्रकार माना जाता है (और जिसे पहले पहचानकर्ता के साथ परिभाषित नहीं किया गया था)?

उत्तर

13

यह केवल इसलिए नहीं है क्योंकि A with B को एक नए प्रकार के रूप में माना जाना चाहिए। स्कैला प्रकार प्रणाली के लिए, यदि A with B से संबंधित कक्षा मौजूद है, तो इससे कोई फर्क नहीं पड़ता है। एक अज्ञात वर्ग उत्पन्न होता है क्योंकि इसमें पुल मिश्रित लक्षणों में सभी विधियों के लिए विधियों को शामिल करना है।

कारण अज्ञात वर्ग बनाया गया है कि वस्तु से सभी विधियों के कार्यान्वयन होना चाहिए A और B से सभी विधियां। जेवीएम बाइटकोड स्तर पर, यह एकाधिक वर्गों को विरासत में वारंट करेगा, और एकाधिक विरासत मॉडल JVM पर समर्थित नहीं है।

एकाधिक वंशानुक्रम अनुकरण के लिए (या mixin रचना, हालांकि आप इसे कॉल करना चाहते हैं), स्काला निम्नलिखित बातें करता है जब आप एक विशेषता बनाने के लिए:

  1. तो विशेषता T कोई विधि कार्यान्वयन है, यह एक बनाता है इंटरफ़ेस जो विशेषता में सभी विधियों को परिभाषित करता है।
  2. यदि विशेषता T में विधि कार्यान्वयन है, तो यह अतिरिक्त रूप से कक्षा T$class बनाता है जिसमें T में प्रत्येक कंक्रीट विधियों के लिए एक स्थिर विधि है। इस स्थैतिक विधि में T में इसी विधि के समान शरीर है, लेकिन this पैरामीटर को शामिल करने के लिए इसका हस्ताक्षर बदल दिया गया है।यदि T था:

    def foo(x: Int) = x 
    

तो T$class होगा:

<static> def foo($this: T, x: Int) = x 

वर्ग कुछ वर्ग A और कुछ विशेषता T की mixin रचना के द्वारा प्राप्त की तो एक विशेष पुल विधि उत्पन्न जो अग्रेषित करता होगा स्थिर विधि को कॉल जिसमें शरीर होता है। इस तरह, विधि का शरीर प्रत्येक वर्ग में डुप्लिकेट नहीं किया जाता है जो T में मिश्रित होता है। यही कारण है कि अनाम वर्ग को बनाया जाना है - इसमें T में प्रत्येक विधि के लिए पुल विधियों को परिभाषित करना होगा।

यहां एक उदाहरण है। जब आप मिश्रित संयोजन करके एक नई कक्षा बनाते हैं, उदा। फोन new A with T:

class A { 
    def bar = println("!") 
} 

<interface> T { 
    def foo(x: Int): Int 
} 

class T$class { 
    <static> def foo($this: T, x: Int) = x 
} 

class $anon extends A <implements> T { 
    // notice that `bar` is inherited, but `foo` is not 
    <bridge> def foo(x: Int) = T$class.foo(this, x) 
} 
new $anon 

सूचना है कि संकलक वास्तव में, foo को callsites पुनर्लेखन सकता है बल्कि callsite से सीधे स्थिर तरीकों कॉल करने के लिए:

class A { 
    def bar = println("!") 
} 

trait T { 
    def foo(x: Int) = x 
} 

new A with T 

संकलक यह मोटे तौर पर कुछ इस तरह करने के लिए फिर से लिखने होगा एक पुल विधि के माध्यम से। यही कारण है कि ऐसा नहीं किया जाता है क्योंकि तब यह सबटाइपिंग पॉलिमॉर्फिज्म का समर्थन नहीं करेगा।

+1

+1 विशेष रूप से एक उदाहरण दिखाने के लिए! –

+1

ग्रेट उत्तर, बहुत बहुत धन्यवाद। –

+0

ध्यान दें कि '-Xprint: mixin' तर्क के साथ 'स्केलैक' को कॉल करना स्कैला बनाता है जो सटीक निर्माण दिखाएगा। '-Xshow-phases' अन्य चरणों को दिखाता है जिनका उपयोग '-Xprint:' के साथ किया जा सकता है। – outis

6

हां। जबकि आपके टाइप अभी भी A with B है, वहां एक अंतर्निहित जावा क्लास होना आवश्यक है जो दोनों इंटरफेस लागू करता है। इसके साथ कुछ भी गलत नहीं है, सिवाय इसके कि यदि आप इस तरह से सैकड़ों बार ऑब्जेक्ट बनाते हैं, तो आपके पास शायद सैकड़ों कक्षा फाइलें होंगी। ऐसे मामले में, आप एक समर्पित class AB extends A with B बनाना और फिर new AB को तत्काल बनाना चाहते हैं।

साइड-नोट के रूप में, आप पाएंगे कि आप सीधे लक्षणों को तुरंत चालू नहीं कर सकते हैं, उदा। new B काम नहीं करेगा। आपको यहां एक स्पष्ट कक्षा भी बनाना है, उदाहरण के लिए, उदा। new B {}, फिर से सिंथेटिक ('अज्ञात') वर्ग में परिणामस्वरूप।

+0

धन्यवाद। जब समर्पित वर्ग प्रदर्शन के संबंध में अधिक समझ में आता है तो अनाम वस्तुओं की संख्या क्या होगी? 10, 100, 1000 या अधिक? –

+3

यह आपके कोड में प्रत्येक घटना के लिए केवल एक नई कक्षा बनाएगा, न कि इस वर्ग के प्रत्येक उदाहरण के लिए। इसलिए जब तक आपके पास सैकड़ों कोड लाइनों में 'बी के साथ नया' नहीं है, जो कि बहुत ही असंभव है, वहां कोई समस्या नहीं होनी चाहिए। – drexin

+0

@ जॉन - मुझे नहीं पता। मैं व्यक्तिगत रूप से पहले से ही 10 मामलों में एक कक्षा होगी; जो 10 अलग-अलग धब्बे हैं जहां 'बी के साथ ए' तत्काल है (जैसा कि @ ड्रेक्सिन सही कहता है)। मेरे पास ऐसे मामलों में अक्सर नहीं होता है। –