यह सीधा नहीं है।
मूल्य का प्रकार कुंजी पर निर्भर करता है। इसलिए कुंजी को जानकारी लेनी है कि इसका मूल्य किस प्रकार है। यह एक आम पैटर्न है। इसका उपयोग एसबीटी में उदाहरण के लिए किया जाता है (उदाहरण के लिए SettingsKey[T] देखें) और बेकार रिकॉर्ड्स (Example)। हालांकि, एसबीटी में चाबियाँ अपने आप की एक विशाल, जटिल श्रेणी पदानुक्रम हैं, और एचएलआईस्ट बेकार में बहुत जटिल है और आप जितना चाहें उतना अधिक करते हैं।
तो यहां एक छोटा उदाहरण है कि आप इसे कैसे कार्यान्वित कर सकते हैं।कुंजी प्रकार को जानता है, और रिकॉर्ड बनाने का एकमात्र तरीका या रिकॉर्ड से मूल्य प्राप्त करने का एकमात्र तरीका कुंजी है। हम एक मानचित्र [कुंजी, कोई भी] आंतरिक रूप से भंडारण के रूप में उपयोग करते हैं, लेकिन जानवरों को छुपाया जाता है और सफल होने की गारंटी दी जाती है। कुंजी से रिकॉर्ड बनाने के लिए एक ऑपरेटर है, और एक ऑपरेटर रिकॉर्ड मर्ज करने के लिए है। मैंने ऑपरेटरों को चुना ताकि आप ब्रैकेट का उपयोग किए बिना रिकॉर्ड्स को जोड़ सकें।
sealed trait Record {
def apply[T](key:Key[T]) : T
def get[T](key:Key[T]) : Option[T]
def ++ (that:Record) : Record
}
private class RecordImpl(private val inner:Map[Key[_], Any]) extends Record {
def apply[T](key:Key[T]) : T = inner.apply(key).asInstanceOf[T]
def get[T](key:Key[T]) : Option[T] = inner.get(key).asInstanceOf[Option[T]]
def ++ (that:Record) = that match {
case that:RecordImpl => new RecordImpl(this.inner ++ that.inner)
}
}
final class Key[T] {
def ~>(value:T) : Record = new RecordImpl(Map(this -> value))
}
object Key {
def apply[T] = new Key[T]
}
यहां बताया गया है कि आप इसका उपयोग कैसे करेंगे।
val a = Key[Int]
val b = Key[String]
val c = Key[Float]
फिर एक रिकॉर्ड
val record = a ~> 1 ++ b ~> "abc" ++ c ~> 1.0f
जब कुंजियों का उपयोग रिकॉर्ड पहुंचने पर, आप वापस सही प्रकार के एक मूल्य मिल जाएगा
scala> record(a)
res0: Int = 1
scala> record(b)
res1: String = abc
scala> record(c)
res2: Float = 1.0
बनाने के लिए उन्हें का उपयोग करें: सबसे पहले कुछ सुझाव दिए परिभाषित
मुझे इस तरह की डेटा संरचना बहुत उपयोगी लगता है। कभी-कभी आपको किसी केस क्लास की तुलना में अधिक लचीलापन की आवश्यकता होती है, लेकिन आप मानचित्र [स्ट्रिंग, कोई भी] की तरह पूरी तरह से टाइप-असुरक्षित कुछ नहीं लेना चाहते हैं। यह एक अच्छा मध्य मैदान है।
संपादित करें: एक और विकल्प एक नक्शा होना चाहिए जो (नाम, प्रकार) जोड़ी को आंतरिक कुंजी के रूप में उपयोग करता है। मूल्य प्राप्त करते समय आपको नाम और प्रकार दोनों प्रदान करना होगा। यदि आप गलत प्रकार चुनते हैं तो कोई प्रविष्टि नहीं है। हालांकि इसमें त्रुटियों के लिए एक बड़ी संभावना है, जैसे कि जब आप एक बाइट डालते हैं और एक int प्राप्त करने का प्रयास करते हैं। तो मुझे लगता है कि यह एक अच्छा विचार नहीं है।
import reflect.runtime.universe.TypeTag
class TypedMap[K](val inner:Map[(K, TypeTag[_]), Any]) extends AnyVal {
def updated[V](key:K, value:V)(implicit tag:TypeTag[V]) = new TypedMap[K](inner + ((key, tag) -> value))
def apply[V](key:K)(implicit tag:TypeTag[V]) = inner.apply((key, tag)).asInstanceOf[V]
def get[V](key:K)(implicit tag:TypeTag[V]) = inner.get((key, tag)).asInstanceOf[Option[V]]
}
object TypedMap {
def empty[K] = new TypedMap[K](Map.empty)
}
उपयोग:
scala> val x = TypedMap.empty[String].updated("a", 1).updated("b", "a string")
x: TypedMap[String] = [email protected]
scala> x.apply[Int]("a")
res0: Int = 1
scala> x.apply[String]("b")
res1: String = a string
// this is what happens when you try to get something out with the wrong type.
scala> x.apply[Int]("b")
java.util.NoSuchElementException: key not found: (b,Int)
http://stackoverflow.com/questions/4309835/scala-reflection/4310959 –