कई स्केल विशिष्टताओं इस व्यवहार को देने के लिए बातचीत करते हैं। पहली बात यह है कि Manifest
एस न केवल कन्स्ट्रक्टर पर गुप्त अंतर्निहित पैरामीटर सूची में शामिल हैं बल्कि कॉपी विधि पर भी शामिल हैं। यह सर्वविदित है कि
case class Foo[+A : Manifest](a: A)
के लिए
case class Foo[+A](a: A)(implicit m: Manifest[A])
बस वाक्यात्मक चीनी है, लेकिन यह भी प्रतिलिपि निर्माता है, जो इस
def copy[B](a: B = a)(implicit m: Manifest[B]) = Foo[B](a)(m)
कैसा दिखेगा को प्रभावित करता है उन सभी implicit m
एस वें द्वारा बनाए गए हैं ई संकलक और अंतर्निहित पैरामीटर सूची के माध्यम से विधि को भेजा।
यह तब तक ठीक रहेगा जब तक कोई copy
विधि का उपयोग उस स्थान पर कर रहा था जहां संकलक Foo
एस प्रकार पैरामीटर जानता था। उदाहरण के लिए, इस बार कक्षा के बाहर काम करेंगे:
val foo = Foo(1)
val aCopy = foo.copy()
println(aCopy.myManifest) // Prints "Int"
यह काम करता है क्योंकि संकलक infers कि foo
एक Foo[Int]
तो यह जानता है foo.a
एक Int
तो यह इस तरह copy
कॉल कर सकते हैं है:
val aCopy = foo.copy()(manifest[Int]())
(ध्यान दें कि manifest[T]()
एक समारोह है कि प्रकार T
, जैसे एक राजधानी "एम" के साथ Manifest[T]
की एक प्रकट प्रतिनिधित्व बनाता है। नहीं दिखाया गया है एक है copy
में डिफ़ॉल्ट पैरामीटर का डीडिशन।) यह Foo
कक्षा के भीतर भी काम करता है क्योंकि इसमें पहले से ही अभिव्यक्ति है जिसे कक्षा के निर्माण के दौरान पारित किया गया था। यह कुछ इस तरह दिखेगा:
case class Foo[+A : Manifest](a: A) {
def myManifest = implicitly[Manifest[_ <: A]]
def localCopy = copy()
}
val foo = Foo(1)
println(foo.localCopy.myManifest) // Prints "Int"
मूल उदाहरण में, तथापि, यह दूसरा विशेष लक्षण की वजह से Bar
कक्षा में विफल रहता है: Bar
के प्रकार के मापदंडों Bar
वर्ग के भीतर जाना जाता है, जबकि, के प्रकार के पैरामीटर प्रकार पैरामीटर नहीं हैं। यह जानता है कि Bar
Foo
या SubFoo
या SubSubFoo
है, लेकिन यदि यह Foo[Int]
या Foo[String]
नहीं है। यह निश्चित रूप से, स्कैला में जाने-माने प्रकार की समस्या है, लेकिन यह एक समस्या के रूप में दिखाई देता है, भले ही ऐसा लगता है कि कक्षा foo
एस प्रकार पैरामीटर के प्रकार से कुछ भी कर रही है। लेकिन यह है, याद रखें कि हर बार copy
को एक मैनिफेस्ट का एक गुप्त इंजेक्शन कहा जाता है, और वे प्रकट होते हैं जो पहले वहां थे।चूंकि Bar
वर्ग है पता नहीं था foo
के प्रकार के पैरामीटर, है यह सिर्फ Any
की एक प्रकट बनाता है और भेजता है साथ इस तरह:
def fooCopy = foo.copy()(manifest[Any])
यदि एक Foo
वर्ग पर नियंत्रण है (उदाहरण के लिए यह नहीं है List
) फिर एक एक विधि जोड़कर फू कक्षा में सभी नकल से अधिक कार्य करके वैकल्पिक हल यह है कि इसके बाद के संस्करण localCopy
तरह उचित नकल करेंगे, है, और परिणाम लौटने:
case class Bar[A <: Foo[Any]](foo: A) {
//def fooCopy = foo.copy()
def fooCopy = foo.localCopy
}
val bar = Bar(Foo(1))
println(bar.fooCopy.myManifest) // Prints "Int"
एक अन्य समाधान Bar
की एक प्रकट प्रकार पैरामीटर के रूप में Foo
रों प्रकार पैरामीटर जोड़ने के लिए है:
case class Bar[A <: Foo[B], B : Manifest](foo: A) {
def fooCopy = foo.copy()
}
लेकिन इस पैमाने खराब करता है, तो वर्ग पदानुक्रम, बड़ी है (अर्थात अधिक सदस्यों के प्रकार पैरामीटर होते हैं, और उन वर्गों में टाइप पैरामीटर भी होते हैं) क्योंकि प्रत्येक वर्ग के नीचे प्रत्येक वर्ग के प्रकार पैरामीटर होना पड़ता है। यह भी प्रकार निष्कर्ष बेकार बाहर बनाने के लिए जब का निर्माण करने की कोशिश कर रहा है एक Bar
:
val bar = Bar(Foo(1)) // Does not compile
val bar = Bar[Foo[Int], Int](Foo(1)) // Compiles
अच्छा काम, मेरे दोस्त! –