मैं रनटाइम पर एक चर का प्रकार प्राप्त करना चाहता हूं


97

मैं रनटाइम पर एक चर का प्रकार प्राप्त करना चाहता हूं। मैं यह कैसे करु?

जवाबों:


132

तो, कड़ाई से बोलते हुए, "एक प्रकार का चर" हमेशा मौजूद होता है, और इसे एक प्रकार के पैरामीटर के रूप में पास किया जा सकता है। उदाहरण के लिए:

val x = 5
def f[T](v: T) = v
f(x) // T is Int, the type of x

लेकिन आप क्या करना चाहते हैं , इसके आधार पर , यह आपकी मदद नहीं करेगा। उदाहरण के लिए, यह जानना नहीं चाह सकते हैं कि चर का प्रकार क्या है, लेकिन यह जानने के लिए कि क्या मूल्य का प्रकार कुछ विशिष्ट प्रकार है, जैसे कि:

val x: Any = 5
def f[T](v: T) = v match {
  case _: Int    => "Int"
  case _: String => "String"
  case _         => "Unknown"
}
f(x)

यहाँ यह कोई फर्क नहीं पड़ता कि चर का प्रकार क्या है Any,। क्या मायने रखता है, क्या जांचा जाता है, का प्रकार है 5, मूल्य। वास्तव में, Tबेकार है - आप इसके def f(v: Any)बजाय इसे लिख सकते हैं। इसके अलावा, यह ClassTagया तो एक मान का उपयोग करता है Class, जिसे नीचे समझाया गया है, और एक प्रकार के प्रकार के मापदंडों की जांच नहीं कर सकता है: आप जांच सकते हैं कि क्या कुछ List[_]( Listकुछ का) है, लेकिन यह नहीं है कि यह उदाहरण के लिए है, List[Int]या एक List[String]

एक अन्य संभावना यह है कि आप चर के प्रकार को संशोधित करना चाहते हैं । यही है, आप प्रकार को एक मूल्य में बदलना चाहते हैं, इसलिए आप इसे स्टोर कर सकते हैं, इसे पास कर सकते हैं, आदि। इसमें प्रतिबिंब शामिल है, और आप ClassTagया तो या एक का उपयोग करेंगे TypeTag। उदाहरण के लिए:

val x: Any = 5
import scala.reflect.ClassTag
def f[T](v: T)(implicit ev: ClassTag[T]) = ev.toString
f(x) // returns the string "Any"

A ClassTagआपको आपके द्वारा प्राप्त किए गए प्रकार के मापदंडों का उपयोग करने देगा match। यह काम नहीं करेगा:

def f[A, B](a: A, b: B) = a match {
  case _: B => "A is a B"
  case _ => "A is not a B"
}

लेकिन यह होगा:

val x = 'c'
val y = 5
val z: Any = 5
import scala.reflect.ClassTag
def f[A, B: ClassTag](a: A, b: B) = a match {
  case _: B => "A is a B"
  case _ => "A is not a B"
}
f(x, y) // A (Char) is not a B (Int)
f(x, z) // A (Char) is a B (Any)

यहां मैं संदर्भ सीमा सिंटैक्स का उपयोग कर रहा हूं B : ClassTag, जो पिछले ClassTagउदाहरण में निहित पैरामीटर की तरह काम करता है , लेकिन एक अनाम चर का उपयोग करता है।

कोई भी इस तरह ClassTagसे मूल्य प्राप्त कर सकता है Class:

val x: Any = 5
val y = 5
import scala.reflect.ClassTag
def f(a: Any, b: Any) = {
  val B = ClassTag(b.getClass)
  ClassTag(a.getClass) match {
    case B => "a is the same class as b"
    case _ => "a is not the same class as b"
  }
}
f(x, y) == f(y, x) // true, a is the same class as b

A इसमें ClassTagसीमित है कि यह केवल आधार वर्ग को कवर करता है, लेकिन इसके प्रकार के मापदंडों को नहीं। है यही कारण है, ClassTagके लिए List[Int]और List[String]एक ही है, List। यदि आपको टाइप पैरामीटर की आवश्यकता है, तो आपको TypeTagइसके बजाय उपयोग करना होगा । एक TypeTagतथापि, JVM के की वजह से एक मूल्य से प्राप्त नहीं किया जा सकता, न ही यह एक पैटर्न मैच पर इस्तेमाल किया जा सकता, विलोपन

इसके उदाहरण TypeTagकाफी जटिल हो सकते हैं - दो प्रकार के टैगों की तुलना करना भी बिल्कुल सरल नहीं है, जैसा कि नीचे देखा जा सकता है:

import scala.reflect.runtime.universe.TypeTag
def f[A, B](a: A, b: B)(implicit evA: TypeTag[A], evB: TypeTag[B]) = evA == evB
type X = Int
val x: X = 5
val y = 5
f(x, y) // false, X is not the same type as Int

बेशक, उस तुलना को सही बनाने के तरीके हैं, लेकिन वास्तव में कवर करने के लिए कुछ पुस्तक अध्यायों की आवश्यकता होगी TypeTag, इसलिए मैं यहां रुकूंगा।

अंत में, शायद आप चर के प्रकार के बारे में बिल्कुल भी परवाह नहीं करते हैं। हो सकता है कि आप केवल जानना चाहते हों कि मूल्य का वर्ग क्या है, जिस स्थिति में उत्तर सरल है:

val x = 5
x.getClass // int -- technically, an Int cannot be a class, but Scala fakes it

हालांकि, यह बेहतर होगा कि आप जो हासिल करना चाहते हैं, उसके बारे में अधिक विशिष्ट होना चाहिए, ताकि उत्तर बिंदु से अधिक हो सके।


"लेकिन यह होगा:" के बाद आपके द्वारा लिखा गया उदाहरण कोड भ्रामक है। यह संकलन करता है लेकिन परिणाम वह नहीं है जो आप टिप्पणियों में दिखाते हैं। दोनों कॉल एक ही परिणाम लौटाते हैं: "ए एक बी है"। क्योंकि मूल्य 5दोनों का एक उदाहरण है Intऔर एक उदाहरण है Any। इसके अलावा, आपका स्पष्टीकरण एकदम सही था :)
पढ़ने वाला

@Readren मान के लिए परीक्षण नहीं किया गया है, वर्ग है। Intहै Any, लेकिन Anyनहीं है Int। यह स्कैला 2.10 पर काम करता है, और इसे स्कला 2.11 पर काम करना चाहिए , और मुझे नहीं पता कि यह क्यों नहीं है।
डैनियल सी। सोबरल

1
यह मुझे आपके जैसे एक प्रतिवाद के विरोध में डराता है, लेकिन कोड a match { case _: B => ...चर के वास्तविक मूल्य के प्रकार का परीक्षण करता है, चर aके प्रकार का नहीं a। आप इसमें सही हैं कि आप 2.10.6 में जो कहते हैं उसे वापस कर देते हैं। लेकिन यह एक बग होना चाहिए। स्कला 2.11.8 में वास्तविक मान के प्रकार का परीक्षण किया जाता है, जैसा कि इसे करना चाहिए।
पढ़ने वाला

क्लासटैग और टाइपटैग के बीच अंतर पर बहुत अच्छा कवरेज, बस मैं क्या देख रहा था।
marcin_koss

वहाँ यह जाँच करने के लिए एक रास्ता है?
चिओमो जुएल

53

मुझे लगता है कि सवाल अधूरा है। यदि आपका मतलब है कि आप कुछ टाइपकास्ट की जानकारी प्राप्त करना चाहते हैं तो नीचे:

यदि आप प्रिंट करना चाहते हैं तो आपने निर्दिष्ट किया है:

scala>  def manOf[T: Manifest](t: T): Manifest[T] = manifest[T]
manOf: [T](t: T)(implicit evidence$1: Manifest[T])Manifest[T]

scala> val x = List(1,2,3)
x: List[Int] = List(1, 2, 3)

scala> println(manOf(x))
scala.collection.immutable.List[Int]

यदि आप उत्तर मोड में हैं तो

scala> :type List(1,2,3)
List[Int]

या यदि आप केवल यह जानना चाहते हैं कि वर्ग प्रकार क्या है तो @monkjack बताते हैं "string".getClassकि यह उद्देश्य हल कर सकता है


3
पाठकों के लिए: यह सबसे उपयोगी उपाय है । जैसा कि जावास्क्रिप्ट में typeof x, यहाँ manOf(x)डेटा प्रकार कहते हैं!
पीटर क्रस

23

यदि एक चर के प्रकार से आपका मतलब उस वस्तु के रनटाइम वर्ग से है जो चर इंगित करता है, तो आप इसे कक्षा संदर्भ के माध्यम से प्राप्त कर सकते हैं जो सभी वस्तुओं में है।

val name = "sam";
name: java.lang.String = sam
name.getClass
res0: java.lang.Class[_] = class java.lang.String

यदि आप फिर भी उस प्रकार का मतलब है जो चर के रूप में घोषित किया गया था, तो आपको वह नहीं मिल सकता है। जैसे, यदि आप कहें

val name: Object = "sam"

तब आपको Stringउपरोक्त कोड से वापस मिल जाएगा ।


8
आप name.getClass.getSimpleNameअधिक पठनीय आउटपुट के लिए भी कर सकते हैं
डेविड अरेनबर्ग

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.