स्कैला में रनटाइम पर क्लास पैरामीटर डेटाटाइप को कैसे खोजें

Nov 29 2020
import scala.reflect.runtime.universe
import scala.reflect.runtime.universe._

def getType[T: TypeTag](obj: T) = typeOf[T]

case class Thing(
  val id: Int,
  var name: String
)
val thing = Thing(1, "Apple")

val dataType = getType(thing).decl(TermName("id")).asTerm.typeSignature

dataType match {
 case t if t =:= typeOf[Int] => println("I am Int")
 case t if t =:= typeOf[String] => println("String, Do some stuff")
 case _ => println("Absurd")
}

पचने में सक्षम नहीं है Absurdइसके बजाय परिणाम क्यों है I am int?

मेरा उद्देश्य रनटाइम के डेटा-प्रकार के क्लास पैरामीटर को जानना और पूर्वनिर्धारित प्रकारों से मिलान करना है।

जवाब

4 DmytroMitin Nov 29 2020 at 17:20

दोनों वर्तमान dataTypeऔर typeOf[Int]के रूप में मुद्रित कर रहे हैं Intलेकिन यदि आप ऐसा showRawआप क्यों वे मेल नहीं खाते देखेंगे

showRaw(dataType) // NullaryMethodType(TypeRef(ThisType(scala), scala.Int, List()))
showRaw(typeOf[Int]) // TypeRef(ThisType(scala), scala.Int, List())

बात यह है कि बस प्रकार Intऔर अशक्त विधि वापसी के Intविभिन्न प्रकार हैं।

जोड़ने की कोशिश करें .resultType

val dataType = getType(thing).decl(TermName("id")).asTerm.typeSignature.resultType

dataType match {
  case t if t =:= typeOf[Int] => println("I am Int")
  case t if t =:= typeOf[String] => println("String, Do some stuff")
  case _ => println("Absurd")
} // I am Int

यह भी ध्यान देने योग्य है कि .decl(TermName("id"))रिटर्न गेटर सिंबल, यह .decl(TermName("id "))(रिक्त स्थान के साथ) है जो फील्ड सिम्बल लौटाता है। तो वैकल्पिक रूप से आप प्रतीक नाम और बिना खाली जगह के साथ कर सकते हैं.resultType

val dataType = getType(thing).decl(TermName("id ")).asTerm.typeSignature

मैं @TomerShetah के उत्तर में जोड़ता हूँ कि यदि लक्ष्य एक केस क्लास के सभी क्षेत्रों में "पैटर्न मैचिंग" है तो यह शेपलेस के साथ संकलन समय (अधिकतर) में भी किया जा सकता है :

import shapeless.Poly1
import shapeless.syntax.std.product._

object printTypes extends Poly1 {
  implicit val int: Case.Aux[Int, Unit] = at(t => println(s"I am Int: $t")) implicit val string: Case.Aux[String, Unit] = at(t => println(s"String, Do some stuff: $t"))
  implicit def default[V]: Case.Aux[V, Unit] = at(t => println(s"Absurd: $t"))
}
  
thing.toHList.map(printTypes)
// I am Int: 1
// String, Do some stuff: Apple

https://scastie.scala-lang.org/DmytroMitin/N4Idk4KcRumQJZE2CHC0yQ

1 TomerShetah Nov 30 2020 at 11:28

@Dmytrio जवाब एक महान स्पष्टीकरण है कि प्रतिबिंब ने आपकी अपेक्षा के अनुरूप काम क्यों नहीं किया।

मैं आपके प्रश्न से समझ सकता हूं, कि आप जो करने की कोशिश कर रहे हैं, वह वास्तव में एक केस क्लास में आपके सभी वेरिएबल्स से मेल खाता है। कृपया इसे निम्नलिखित तरीके से करने पर विचार करें:

case class Thing(id: Int, name: String)
val thing = Thing(1, "Apple")

thing.productIterator.foreach {
  case t: Int => println(s"I am Int: $t") case t: String => println(s"String, Do some stuff: $t")
  case t => println(s"Absurd: $t")
} 

स्कैस्टी में कोड रन ।