Scala Language
प्रकार वर्ग
खोज…
टिप्पणियों
सीरियलाइज़ेशन की समस्याओं से बचने के लिए, विशेष रूप से वितरित वातावरण (जैसे अपाचे स्पार्क ) में, टाइप क्लास उदाहरणों के लिए Serializable
विशेषता को लागू करने के लिए यह सबसे अच्छा अभ्यास है।
सिंपल टाइप क्लास
एक प्रकार का वर्ग केवल एक या अधिक प्रकार के मापदंडों के साथ एक trait
:
trait Show[A] {
def show(a: A): String
}
एक प्रकार की कक्षा का विस्तार करने के बजाय, प्रत्येक समर्थित प्रकार के लिए प्रकार वर्ग का एक निहित उदाहरण प्रदान किया जाता है। टाइप क्लास के साथी ऑब्जेक्ट में इन कार्यान्वयनों को रखने से किसी विशेष आयात के बिना कार्य करने के लिए निहित संकल्प की अनुमति मिलती है:
object Show {
implicit val intShow: Show[Int] = new Show {
def show(x: Int): String = x.toString
}
implicit val dateShow: Show[java.util.Date] = new Show {
def show(x: java.util.Date): String = x.getTime.toString
}
// ..etc
}
यदि आप यह गारंटी देना चाहते हैं कि फ़ंक्शन के लिए दिया गया जेनेरिक पैरामीटर एक प्रकार की श्रेणी का उदाहरण है, तो निहित मापदंडों का उपयोग करें:
def log[A](a: A)(implicit showInstance: Show[A]): Unit = {
println(showInstance.show(a))
}
आप एक संदर्भ सीमा का उपयोग भी कर सकते हैं:
def log[A: Show](a: A): Unit = {
println(implicitly[Show[A]].show(a))
}
उपरोक्त log
विधि को किसी अन्य विधि की तरह कॉल करें। यह संकलन करने असफल हो जायेगी एक अंतर्निहित अगर Show[A]
लागू करने के लिए नहीं पाया जा सकता A
आप के पास log
log(10) // prints: "10"
log(new java.util.Date(1469491668401L) // prints: "1469491668401"
log(List(1,2,3)) // fails to compile with
// could not find implicit value for evidence parameter of type Show[List[Int]]
यह उदाहरण Show
प्रकार वर्ग को लागू करता है। यह एक सामान्य प्रकार का वर्ग है जिसका उपयोग मनमाने प्रकार के उदाहरणों को String
एस में परिवर्तित करने के लिए किया जाता है। भले ही हर वस्तु में एक toString
विधि होती है, लेकिन यह हमेशा स्पष्ट नहीं होता है कि क्या एक उपयोगी तरीके से toString
को परिभाषित किया गया है या नहीं। Show
प्रकार वर्ग के उपयोग के साथ, आप गारंटी दे सकते हैं कि log
करने के लिए पारित कुछ भी String
लिए एक अच्छी तरह से परिभाषित रूपांतरण है।
एक प्रकार वर्ग का विस्तार
इस उदाहरण में निम्न प्रकार वर्ग के विस्तार पर चर्चा की गई है।
trait Show[A] {
def show: String
}
एक वर्ग बनाने के लिए जिसे आप नियंत्रित करते हैं (और स्कैला में लिखा जाता है) प्रकार की कक्षा का विस्तार करते हैं, इसके साथी ऑब्जेक्ट में निहित जोड़ते हैं। हमें बताएंगे कि कैसे हम प्राप्त कर सकते हैं Person
से वर्ग इस उदाहरण का विस्तार करने के Show
:
class Person(val fullName: String) {
def this(firstName: String, lastName: String) = this(s"$firstName $lastName")
}
हम इस वर्ग का विस्तार कर सकते हैं Person
के साथी वस्तु के लिए एक जोड़कर Show
:
object Person {
implicit val personShow: Show[Person] = new Show {
def show(p: Person): String = s"Person(${p.fullname})"
}
}
एक साथी ऑब्जेक्ट क्लास के समान फ़ाइल में होना चाहिए , इसलिए आपको एक ही फ़ाइल में class Person
और object Person
दोनों की आवश्यकता होगी।
एक वर्ग बनाने के लिए जिसे आप नियंत्रित नहीं करते हैं, या स्कैला में नहीं लिखा जाता है, टाइप क्लास का विस्तार करें, टाइप क्लास के साथी ऑब्जेक्ट के लिए एक अंतर्निहित जोड़ें, जैसा कि सिंपल टाइप क्लास उदाहरण में दिखाया गया है।
यदि आप न तो क्लास और न ही टाइप क्लास को नियंत्रित करते हैं, तो ऊपर कहीं भी एक निहितार्थ बनाएं और इसे import
। सरल प्रकार वर्ग उदाहरण पर log
विधि का उपयोग करना:
object MyShow {
implicit val personShow: Show[Person] = new Show {
def show(p: Person): String = s"Person(${p.fullname})"
}
}
def logPeople(persons: Person*): Unit = {
import MyShow.personShow
persons foreach { p => log(p) }
}
टाइप करने के लिए टाइप क्लास फ़ंक्शंस जोड़ें
स्काला के प्रकारों का कार्यान्वयन क्रियात्मक है। वर्बोसिटी को कम करने का एक तरीका तथाकथित "ऑपरेशन क्लासेस" को पेश करना है। जब कार्यक्षमता का विस्तार करने के लिए इन वर्गों को स्वचालित रूप से एक चर / मान लपेटेंगे।
इसे समझने के लिए, आइए हम पहले एक साधारण प्रकार की क्लास बनाएँ:
// The mathematical definition of "Addable" is "Semigroup"
trait Addable[A] {
def add(x: A, y: A): A
}
आगे हम गुणन को लागू करेंगे (टाइप क्लास को तत्काल):
object Instances {
// Instance for Int
// Also called evidence object, meaning that this object saw that Int learned how to be added
implicit object addableInt extends Addable[Int] {
def add(x: Int, y: Int): Int = x + y
}
// Instance for String
implicit object addableString extends Addable[String] {
def add(x: String, y: String): String = x + y
}
}
फिलहाल यह हमारे जोड़ने योग्य उदाहरणों का उपयोग करने के लिए बहुत बोझिल होगा:
import Instances._
val three = addableInt.add(1,2)
हम केवल 1.add(2)
लिखना 1.add(2)
। इसलिए हम एक "ऑपरेशन क्लास" (जिसे "ऑप्स क्लास" भी कहा जाता है) Addable
जो हमेशा एक प्रकार से अधिक Addable
जो कि Addable
लागू Addable
।
object Ops {
implicit class AddableOps[A](self: A)(implicit A: Addable[A]) {
def add(other: A): A = A.add(self, other)
}
}
अब हम अपने नए फंक्शन add
उपयोग कर सकते add
जैसे कि यह Int
और String
का हिस्सा था:
object Main {
import Instances._ // import evidence objects into this scope
import Ops._ // import the wrappers
def main(args: Array[String]): Unit = {
println(1.add(5))
println("mag".add("net"))
// println(1.add(3.141)) // Fails because we didn't create an instance for Double
}
}
"ऑप्स" कक्षाएं सिमुलकराम लाइब्रेरी में मैक्रोज़ द्वारा स्वचालित रूप से बनाई जा सकती हैं:
import simulacrum._
@typeclass trait Addable[A] {
@op("|+|") def add(x: A, y: A): A
}