2011-12-15 14 views
5

पुस्तक "स्काला में प्रोग्रामिंग" के अध्याय 22 में, :: वर्ग (विपक्ष)स्काला अंतिम मामले वर्ग के साथ नए का उपयोग

final case class ::[T](hd: T, tl: List[T]) extends List[T] { 
    //... 
} 

:: पद्धति के रूप में वर्ग List में परिभाषित किया गया है इस प्रकार परिभाषित किया गया है:

def ::[U >: T](x: U): List[U] = new scala.::(x, this) 

क्यों newfinalcaseclass :: का एक उदाहरण बनाने के लिए आवश्यक है? क्या यह पूरी तरह से असंबद्धता के लिए है?

+4

अंतिम केवल इसका मतलब है कि कक्षा को विस्तारित नहीं किया जा सकता है, इसका उदाहरण उदाहरण के साथ कुछ भी नहीं है :-)। केस क्लास मूल रूप से एक वर्ग है जिसे 'मैच केस' ब्लॉक में तुलना की जा सकती है। – aishwarya

उत्तर

6

मामले वर्गों के साथ आप स्वचालित रूप से एक साथी वस्तु जिसका apply विधि निर्माता कॉल मिलता है उसी तरह से के रूप में आप एक साधारण वर्ग के साथ ऐसा कर सकते हैं:

class Foo(val value: Int) 
object Foo { def apply(value: Int) = new Foo(value) } 

val x = new Foo(42) // 
val y = Foo(42)  // both work the same 

आप new के मामले में कक्षाओं का दृष्टांत सकते हैं यदि आप चाहना। यह सिद्धांत में थोड़ा तेज़ हो सकता है क्योंकि इसे साथी ऑब्जेक्ट की apply विधि के माध्यम से जाना नहीं है, लेकिन मैंने त्वरित बेंचमार्क की कोशिश की और प्रदर्शन में बिल्कुल कोई फर्क नहीं पड़ता, इसलिए मुझे लगता है कि यह संकलक द्वारा अनुकूलित किया गया है, या केवल एक छोटा सा छोटा वास्तविक निर्माण की तुलना में अंतर।

इसलिए मुझे नहीं लगता कि आपके द्वारा दिए गए उदाहरण में new का कोई महत्व है और इसे छोड़ दिया जा सकता है।

3

आप सही हैं; new अनिवार्य नहीं है। वे बस के रूप में अच्छी तरह से इस तरह उदाहरण विधि List#:: परिभाषित किया जा सकता था:

def ::[U >: T](x: U): List[U] = scala.::(x, this) 

(नोट है कि हम:

type :: = collection.immutable.:: 
val :: = collection.immutable.:: 

scala पैकेज वस्तु में परिभाषित किया गया है, पहले यही कारण है कि अपने new scala.::(x, this) काम करता है, और दूसरी बात यह है कि मेरा scala.::(x, this) काम करता है।)

The form the library uses आपके जैसा काम करता है, सीधे निर्माता को कॉल करता है। विकल्प apply:: केस क्लास के लिए जेनरेट की गई सिंथेटिक साथी ऑब्जेक्ट की विधि को कॉल करता है, जो कि कन्स्ट्रक्टर को वैसे भी कॉल करता है। शायद कन्स्ट्रक्टर को बुलाकर स्पष्ट, या अधिक कुशल समझा गया था? (। दक्षता लाभ कुछ भी नहीं के करीब है, हालांकि, होना चाहिए, क्योंकि यदि संकलक apply करने के लिए कॉल इनलाइन नहीं करता है, JVM जाएगा) मैं सबसे संक्षिप्त रूप लगता है:

def ::[U >: T](x: U) = ::(x, this) 

कुछ निराला के लिए गलत हो सकता है (यानी असंभव) पुनरावर्ती आमंत्रण की तरह, और किसी भी दर पर :: नामक कक्षा के बीच भेद और List विधि :: नामक विधि को प्रभावित करती है, जो प्रोफेसर ओडर्स्की को पाठक समझ को अधिकतम करने के लिए अलग रखने के लिए दर्द होता है।

उम्मीद है कि इससे मदद मिलती है।

संबंधित मुद्दे