2010-12-17 13 views
14

के उपयोग की व्याख्या करें स्कैला के विकल्प वर्ग में orNull विधि है, जिसका हस्ताक्षर नीचे दिखाया गया है।कृपया विकल्प या नल विधि

orNull [A1 >: A](implicit ev : <:<[Null, A1]) : A1 

मैं निहित चीज़ से परेशान हूं। क्या कोई कृपया बताएगा कि इसका उपयोग कैसे किया जा सकता है, आदर्श रूप से उदाहरण के साथ?

+6

ओह, स्रोत कोड का उपयोग करता है 'अशक्त <:

उत्तर

26
scala> Some(1).orNull 
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int] 
     Some(1).orNull 
      ^
scala> (None : Option[Int]).orNull 
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int] 
     (None : Option[Int]).orNull 

scala> Some("hi").orNull 
res21: java.lang.String = hi 

scala> Some(null : String).orNull 
res22: String = null 

scala> (None : Option[String]).orNull 
res23: String = null 

अंतर्निहित बात समझाने के लिए: orNull कुछ से वापस पाने का एक तरीका है | जावा के मूल्य के लिए कोई भी मुहावरा | अशक्त मुहावरा (जो निश्चित रूप से है, बुरा)। अब केवल AnyRef मान (कक्षाओं के उदाहरण) एक शून्य मान स्वीकार कर सकते हैं।

तो हमें क्या पसंद आया def orNull[A >: Null] = .... है। लेकिन ए पहले ही सेट है और हम इसे विशेषता की परिभाषा में प्रतिबंधित नहीं करना चाहते हैं। इसलिए, या नल एक सबूत की अपेक्षा करता है कि ए एक शून्य प्रकार है। ': A1 अशक्त <' यह सबूत एक अंतर्निहित चर (इसलिए नाम 'EV')

<:<[Null, A1]Null <:< A1 के रूप में लिखा जा सकता है इस तरह इसे देखने के रूप में है, यह करने के लिए समान है। <: < को प्रिडफ में परिभाषित किया गया है और साथ ही विधि जो conforms नामक निहित मूल्य प्रदान करती है।

मुझे लगता है कि A1 का उपयोग सख्त यहाँ की आवश्यकता नहीं है और है, क्योंकि orNull getOrElse (जहां डिफ़ॉल्ट दिया एक का एक सुपर प्रकार हो सकता है)

scala> class Wrapper[A](option: Option[A]) { 
    | def orNull(implicit ev: Null <:< A): A = if(option.isEmpty) null else option.get 
    | } 
defined class Wrapper 

scala> new Wrapper(Some("hi")).orNull 
res18: java.lang.String = hi 
+4

इस तरह की चीजें देखकर, वास्तव में स्कैला को प्यार करना मुश्किल नहीं है। – Madoc

+2

पुस्तकालय लेखकों को मॉड्यूलर बनाने और अच्छी तरह से काम करने के लिए एक लंबा रास्ता तय करते हैं; नकारात्मकता यह है कि हस्ताक्षर अक्सर बाहरी व्यक्ति के लिए बिल्कुल अजीब लगते हैं, और त्रुटि संदेश अनजान हैं। एक अच्छी युक्ति इसे अनदेखा कर सकती है और केवल दस्तावेज़ीकरण को पढ़ सकती है। :-) –

4

याद रखें कि स्कैला आदिम प्रकारों और संदर्भ प्रकारों में एकीकृत हैं - लेकिन केवल संदर्भ प्रकार शून्य हैं। निहित बस संकलक को यह पुष्टि करने की अनुमति देता है कि ए 1 एक संदर्भ प्रकार है।

+0

ठीक है। क्या आप मुझे इसके उपयोग का एक उदाहरण देंगे? – David

+0

इसे रद्द करें; IttayD ने एक उदाहरण प्रदान किया है। "प्रोग्रामिंग स्कैला" का यह अनुभाग प्रासंगिक प्रतीत होता है: http://programming-scala.labs.oreilly.com/ch12.html#NothingAndNull। – David

5

orNull उद्देश्य संगतता सुनिश्चित करने में सब से पहले है का उपयोग करता है जावा के साथ Option का। हालांकि null का उपयोग स्कैला में निराश है, कुछ इंटरफेस को शून्य संदर्भों की उम्मीद है।

orNull एक सीधी कार्यान्वयन है:

def orNull[A1 >: A](implicit ev: Null <:< A1): A1 = this getOrElse null 

इस के अनुसार, null लौटा दी जाएगी न केवल बॉक्स्ड nulls (Some(null)) के लिए, लेकिन यह भी None (उदाहरण के लिए, यदि आप None.get कहते हैं, अपवाद फेंक दिया जाएगा)।

लागू पैरामीटर चेक, यदि बॉक्स किए गए मान को शून्य है।

अच्छा उपयोग का उदाहरण देखने comments to orNull में सही पाया जा सकता है:

val initialText: Option[String] = getInitialText 
val textField = new JComponent(initialText.orNull,20) 
+1

बस इसे और अधिक स्पष्ट करने के लिए: यह केवल संदर्भ प्रकारों (AnyRef के उपप्रकारों) के लिए काम करता है लेकिन मूल्य प्रकार (AnyVal का उप प्रकार) के लिए नहीं, क्योंकि उनके पास कोई शून्य मान नहीं है। –

+0

तो क्या होगा, getInitialText पाने के बजाय, आपको InitialNum मिल गया था, लंबे समय तक लौट रहा था? मान लीजिए कि आप उस लंबी संख्या को जावा में पास करना चाहते थे, या शून्य अगर इसे परिभाषित नहीं किया गया था। – David

+1

फिर आपको स्केल के बजाय 'java.lang.Long' निर्दिष्ट करने के लिए टाइप लिप्यंतरण का उपयोग करने की आवश्यकता है। लांग':' वैल प्रारंभिक पाठ: विकल्प [java.lang.Long] = getInitialLong' –

2

को समझने के लिए क्यों यह उपयोगी है, IttayD provided a nice explanation:

तो क्या हम इसे पसंद किया है | डीईएफ़ orNull[A >: Null] = ..... है, लेकिन एक है पहले से सेट है और हम विशेषता की परिभाषा में प्रतिबंधित नहीं करना चाहते हैं। इसलिए, या नल सबूत की अपेक्षा करता है कि ए एक शून्य प्रकार है। यह सबूत एक अंतर्निहित चर (इसलिए नाम 'EV')

सारांश में के रूप में है, टाइप की कमी उपयोगी है जब आप तरीकों (जैसे orNull) एक सामान्य वर्ग पर (जैसे Option चाहते हैं) कक्षा के मुकाबले अधिक विशिष्ट बाधाओं (जैसे Null <: A <: Any) के साथ (उदाहरण के लिए A <: Any)।

यह एक और "फीचर" है जो भाषा में नहीं बनाया गया है, लेकिन निहित पैरामीटर और टाइप पैरामीटर के भिन्नता एनोटेशन के लिए मुफ्त धन्यवाद के लिए आता है। यह समझने के लिए, <:< की परिभाषा को देखो:

// from Predef  
sealed abstract class <:<[-From, +To] extends (From => To) 
implicit def conforms[A]: A <:< A = new (A <:< A) {def apply(x: A) = x} 

लिए

scala> Some(1).orNull 
<console>:10: error: could not find implicit value for parameter ev: <:<[Null,Int] 
     Some(1).orNull 

संकलक प्रकार <:<[Null, Int] का एक अंतर्निहित मूल्य के लिए लग रहा है और विधि def conforms[A]: A <:< A मिल जाएगा। तो A होना चाहिए जिसके लिए <:<[A, A]<:<[Null, Int] के अनुरूप है। इसमें कोई A नहीं है जिसके लिए यह धारण करता है और नतीजतन संकलक लापता निहित मूल्य के बारे में शिकायत करेगा।

हालांकि, के लिए

scala> Some("hi").orNull 
res21: java.lang.String = hi 

हम भाग्यशाली रहे हैं। अब, संकलक A खोजने की कोशिश करता है जिसके लिए <:<[A, A]<:<[Null, String] के अनुरूप है। यह A = String के लिए काम करता है, क्योंकि NullString का उप प्रकार है और From वर्ग <:< के प्रकार पैरामीटर को contravariant के रूप में परिभाषित किया गया है)।

जैसा कि बताया गया है, प्रकार की बाधाओं के बारे में सोचने का सबसे सहज तरीका इसे एक प्रकार की तरह पढ़ रहा है (यानी इसे नल <: Int) के रूप में पढ़ना। NullInt के अनुरूप नहीं है और <: < [Null, Int] के लिए कोई अंतर्निहित मूल्य नहीं है। दूसरी ओर, NullString के अनुरूप है और संकलक को अंतर्निहित पैरामीटर मिलेगा।

वैसे, यहां एक और related answer है।

0

पुन: 'यह कैसे उपयोग किया जाता है' - एक जगह जहां हमें यह उपयोगी लगता है जब जावा एपी मैपिंग से निपटने पर null आम है, उदा। jdbc पर nullable एसक्यूएल कॉलम के लिए तैयार बयान पर। Option अल आंतरिक मॉडल क्षेत्रों मैप किया जा सकता:

stmt.setDate("field", myModel.myDateField.orNull) 
अधिक वर्बोज़ के बजाय

:

stmt.setDate("field", myModel.myDateField.getOrElse(null)) 
संबंधित मुद्दे