2012-10-09 23 views
11

कहते हैं कि मैं इस वर्गस्कैला में, ऑब्जेक्ट के मानों को मानचित्र [स्ट्रिंग, स्ट्रिंग] में कैसे चालू करें?

case class Test (id: Long, name: String) 

और इस वर्ग का एक उदाहरण है दो:

Test : 
id -> 1 
name -> toto 

मैं एक मानचित्र [स्ट्रिंग, स्ट्रिंग] इस प्रकार बनाना चाहेंगे:

Map("id" -> "1", "name" -> "toto") 

मेरा सवाल है: क्या टेस्ट के इस उदाहरण को मैप [स्ट्रिंग, स्ट्रिंग] में बदलने का कोई तरीका है? मैं इस एक के रूप में एक विधि का उपयोग करने से बचना चाहते हैं:

def createMap(instance: Test): Map[String, String] = { 
    val map = new Map[String, String] 
    map.put("id", instance.id.toString) 
    map.put("name", instance.name) 
    map 
} 

अगर वहाँ स्काला में ऐसा करने की कोई विधि नहीं है, वहाँ वर्ग गुण से अधिक पुनरावृति करने के लिए एक तरीका है? शायद मैं ऐसा करने के लिए एक सामान्य कार्य बना सकता हूं:

def createMap(instance: T): Map[String, String] = { 
    val map = new Map[String, String] 
    //pseudocode 
    for ((name, value) <- instance.getClassProperties.getValues) { 
     case value.isInstanceOf[String] : map.push(name, value) 
     case _ : map.push(name, value.toString) 
    } 
    map 
} 

क्या यह संभव है? यदि आपके पास अच्छे उदाहरण/लिंक हैं, तो मुझे रूचि है।

+0

[इस प्रश्न] के जवाब [http://stackoverflow.com/questions/2224251/reflection-on-a-scala-case-class) मदद कर सकते हैं। – incrop

+0

ऐसा नहीं है कि मुझे सामान्य समाधान पसंद नहीं हैं, लेकिन इस समस्या के लिए मैं 'मानचित्र ("आईडी" -> t.id.toString, "name" -> t.name) का उपयोग करूंगा, जहां 't' का उदाहरण है 'Test'। – sschaef

+0

टिप के लिए धन्यवाद! – alexgindre

उत्तर

19

हाँ यह संभव है: आप और अधिक जानने में रुचि रखते हैं, एक अच्छा प्रवेश बिंदु इस पोस्ट हो सकता है। स्कैला 2.10 के बाद से आप प्रतिबिंब का उपयोग कर सकते हैं।

आप यह मानते हुए है:

val test = Test(23423, "sdlkfjlsdk") 

निम्नलिखित आप क्या चाहते हैं आप मिल जाएगा:

import reflect.runtime.universe._ 
import reflect.runtime.currentMirror 

val r = currentMirror.reflect(test) 
r.symbol.typeSignature.members.toStream 
    .collect{case s : TermSymbol if !s.isMethod => r.reflectField(s)} 
    .map(r => r.symbol.name.toString.trim -> r.get.toString) 
    .toMap 

बस अपने उदाहरण पर मामला वर्ग उपयोग .productIterator के क्षेत्र मूल्यों पर पुनरावृति करने के लिए।

+0

क्या यह प्रक्रिया उलटी हो सकती है ?? मानचित्र से ऑब्जेक्ट तक? यदि वर्ग का पूरा नाम –

+1

@ जेफली हां दिया गया है। प्रतिबिंब और मैक्रोज़ दोनों के साथ यह संभव है। यहां [स्कैला 2.10] के प्रतिबिंब का उपयोग करके एक उदाहरण है (https://github.com/sorm/sorm/blob/master/src/main/scala/sorm/reflection/Reflection.scala#L50-L58)। –

10

जिस विषय से आप काम कर रहे हैं वह स्टैक ओवरफ्लो पर अविश्वसनीय रूप से आवर्ती हो रहा है और यदि आप टाइपएफ़ कार्यान्वयन करना चाहते हैं तो समस्या छोटी नहीं है।

समस्या को हल करने का एक तरीका प्रतिबिंब (सुझाए गए अनुसार) का उपयोग कर रहा है लेकिन मैं व्यक्तिगत रूप से प्रकार प्रणाली और implicits का उपयोग करना पसंद करता हूं।

एक बेहद सुन्दर लाइब्रेरी द्वारा विकसित एक प्रसिद्ध पुस्तकालय है, जो आपको किसी भी केस क्लास को टाइपएफ़ विषम सूची में बदलने या हेटेरगिनस मैप्स बनाने के लिए उन्नत संचालन करने देता है, जिसका उपयोग "एक्स्टेंसिबल" को लागू करने के लिए किया जा सकता है रिकॉर्ड "। पुस्तकालय निराकार एक उदाहरण कहा जाता है, और यहाँ है:

object RecordExamples extends App { 
    import shapeless._ 
    import HList._ 
    import Record._ 

    object author extends Field[String] { override def toString = "Author" } 
    object title extends Field[String] { override def toString = "Title" } 
    object id  extends Field[Int]  { override def toString = "ID" } 
    object price extends Field[Double] { override def toString = "Price" } 
    object inPrint extends Field[Boolean] { override def toString = "In print" } 

    def printBook[B <: HList](b : B)(implicit tl : ToList[B, (Field[_], Any)]) = { 
    b.toList foreach { case (field, value) => println(field+": "+value) } 
    println 
    } 

    val book = 
    (author -> "Benjamin Pierce") :: 
    (title -> "Types and Programming Languages") :: 
    (id  -> 262162091) :: 
    (price -> 44.11) :: 
    HNil 

    printBook(book) 

    // Read price field 
    val currentPrice = book.get(price) // Static type is Double 
    println("Current price is "+currentPrice) 
    println 

    // Update price field, relying on static type of currentPrice 
    val updated = book + (price -> (currentPrice+2.0)) 
    printBook(updated) 

    // Add a new field 
    val extended = updated + (inPrint -> true) 
    printBook(extended) 

    // Remove a field 
    val noId = extended - id 
    printBook(noId) 
} 

बुक एक typesafe नक्शा जो कुंजी के रूप में वस्तुओं का उपयोग करके अनुक्रमित कर सकते हैं की तरह व्यवहार करता है।

Are HLists nothing more than a convoluted way of writing tuples?

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