2011-10-12 11 views
5

में वैकल्पिक xml विशेषताओं को प्रोसेस करना मेरे पास एक XML फ़ाइल पढ़ने वाला कोड है। उन तत्वों के कुछ गुण जिन्हें मुझे संसाधित करने की आवश्यकता है वे वैकल्पिक हैं। मैं उन्हें प्रबंधित करने के लिए विकल्प [टी] का उपयोग करने की कोशिश कर रहा हूं। मैं लिखा है \ नोड ऑपरेटर द्वारा दिया NodeSeq प्रकार दलाल करने के लिए निम्नलिखित:स्कैला

(node \ "@attr").textOption.getOrElse("Some default value") 

नोड "attr" विशेषता है, तो यह कोड:

class NodeSeqWrapper(nodeSeq: NodeSeq) { 
    def textOption: Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 
} 
implicit def nodeSeqWrapper(nodeSeq: NodeSeq): NodeSeqWrapper = 
    new NodeSeqWrapper(nodeSeq) 

और उसके बाद इस तरह इसे कहते यह मूल्य प्राप्त करता है। यदि ऐसा नहीं होता है, तो मान "कुछ डिफ़ॉल्ट मान" वापस कर दिया जाता है।

मैं इसे कैसे सुधार सकता हूं? क्या पाठ्यक्रम परिभाषा को अंतर्निहित विधि में फोल्ड करने का कोई तरीका है? क्या "वैकल्पिक" विशेषता मान प्राप्त करने का कोई बेहतर तरीका है? क्या मैं Option[T] "सही" का उपयोग कर रहा हूं?

+0

आप अपनी विधि 'टेक्स्टऑप्शन' को उसी शैली में 'सेक' के 'हेड' और 'हेडऑप्शन' विधियों के रूप में कॉल करना चाह सकते हैं। –

+0

अच्छा लगता है। मैं अपना कोड बदल दूंगा। प्रश्न भी अपडेट कर रहा है। – Ralph

उत्तर

4

मैं कहूंगा कि आप इसे एक बहुत ही मूर्ख तरीके से कर रहे हैं, हां।

आप "परिभाषाएँ एक तह" कर सकते हैं इस प्रकार है:

implicit def enrichNodeSeq(nodeSeq: NodeSeq) = new AnyRef { 
    def textOption : Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 
} 

आप हमेशा परिणाम पर .getOrElse(...) आवेदन कर रहे हैं, तो आप भी एक दूसरे संस्करण textOrElse(elze : String) : String को परिभाषित करना चाहते हो सकता है:

implicit def enrichNodeSeq(nodeSeq: NodeSeq) = new AnyRef { 
    def textOption : Option[String] = { 
    val text = nodeSeq.text 
    if (text == null || text.length == 0) None else Some(text) 
    } 

    def textOrElse(elze : String) : String = textOption.getOrElse(elze) 
} 

कि चीजों को थोड़ा और संक्षिप्त बना देगा।

scala> (<b>Hello</b> : NodeSeq).textOrElse("No text found.") 
resN: String = Hello 
scala> (<br /> : NodeSeq).textOrElse("No text found.") 
resM: String = No text found. 
+0

यही वह है जिसे मैं ढूंढ रहा था। मैंने अपने पहले प्रयास ('नया {...} ') में एक अज्ञात वर्ग का उपयोग करने की कोशिश की और यह काम नहीं किया। मुझे 'textOrElse' विधि भी पसंद है। धन्यवाद। – Ralph

+2

सावधान रहें कि "परिभाषाओं को फोल्ड करना" प्रत्येक बार जब आप अपनी अतिरिक्त विधियों को कॉल करते हैं तो जावा प्रतिबिंब का उपयोग किया जाता है। अतिरिक्त कक्षा घोषित नहीं करता है। –

+0

@ जीन-फिलिपपेलेट अच्छा बिंदु! मुझे संदेह होगा कि जेवीएम जेआईटी कंपाइलर प्रतिबिंबित कॉल को संभालने में काफी अच्छा है जहां विधि का नाम स्थिर स्ट्रिंग के रूप में दिया जाता है। – Philippe

2

अंतर्निहित कक्षाओं के परिचय के साथ स्कैला 2.10 के बाद से उत्तर में सुधार किया जा सकता है।

http://docs.scala-lang.org/overviews/core/implicit-classes.html

उदाहरण सेशन दिया जा सकता है ताकि तरह एक अंतर्निहित वर्ग का उपयोग कर फिर से लिखा जा:

object SomeExtensions { 

    implicit class ExtendedNodeSeq(nodeSeq: NodeSeq) { 
    def textOption: Option[String] = { 
     val text = nodeSeq.text 
     if (text == null || text.length == 0) None else Some(text) 
    } 
    } 

} 

ध्यान दें कि उदाहरण के मामले कक्षाओं के लिए प्रतिबंध के एक जोड़े इस प्रकार है:

  1. उन्हें किसी अन्य विशेषता/वर्ग/वस्तु के अंदर परिभाषित किया जाना चाहिए।
  2. वे केवल अपने कन्स्ट्रक्टर में एक गैर-निहित तर्क ले सकते हैं।