खोज…


वाक्य - विन्यास

  • मामला वर्ग Foo () // बिना किसी पैरामीटर वाले केस वर्गों की एक खाली सूची होनी चाहिए
  • केस क्लास फू (ए 1: ए 1, ..., ए एन: एएन) // फ़ील्ड ए 1 ... ए एन के साथ केस क्लास बनाएं
  • केस ऑब्जेक्ट बार // एक सिंगलटन केस क्लास बनाएं

केस क्लास इक्वलिटी

केस क्लासेस द्वारा मुफ्त में प्रदान की जाने वाली एक विशेषता एक ऑटो-जनरेटेड equals तरीका है, जो वस्तुओं के संदर्भ समानता की जांच करने के बजाय सभी व्यक्तिगत सदस्य क्षेत्रों के मूल्य समानता की जांच करता है।

साधारण वर्गों के साथ:

class Foo(val i: Int)
val a = new Foo(3)
val b = new Foo(3)
println(a == b)// "false" because they are different objects

केस कक्षाओं के साथ:

case class Foo(i: Int)
val a = Foo(3)
val b = Foo(3)
println(a == b)// "true" because their members have the same value

जनरेट कोड कलाकृतियाँ

case संशोधक स्काला संकलक को वर्ग के लिए सामान्य बॉयलरप्लेट कोड उत्पन्न करने का कारण बनता है। इस कोड को मैन्युअल रूप से लागू करना थकाऊ और त्रुटियों का स्रोत है। निम्नलिखित केस क्लास परिभाषा:

case class Person(name: String, age: Int)

... निम्नलिखित कोड स्वतः उत्पन्न होगा:

class Person(val name: String, val age: Int)
  extends Product with Serializable
{
  def copy(name: String = this.name, age: Int = this.age): Person =
    new Person(name, age)

  def productArity: Int = 2

  def productElement(i: Int): Any = i match {
    case 0 => name
    case 1 => age
    case _ => throw new IndexOutOfBoundsException(i.toString)
  }

  def productIterator: Iterator[Any] =
    scala.runtime.ScalaRunTime.typedProductIterator(this)

  def productPrefix: String = "Person"

  def canEqual(obj: Any): Boolean = obj.isInstanceOf[Person]

  override def hashCode(): Int = scala.runtime.ScalaRunTime._hashCode(this)

  override def equals(obj: Any): Boolean = this.eq(obj) || obj match {
    case that: Person => this.name == that.name && this.age == that.age
    case _ => false
  }

  override def toString: String =
    scala.runtime.ScalaRunTime._toString(this)
}

case संशोधक भी एक साथी वस्तु उत्पन्न करता है:

object Person extends AbstractFunction2[String, Int, Person] with Serializable {
  def apply(name: String, age: Int): Person = new Person(name, age)

  def unapply(p: Person): Option[(String, Int)] =
    if(p == null) None else Some((p.name, p.age))
}

जब किसी object लागू किया जाता object , तो case संशोधक समान (यद्यपि कम नाटकीय) प्रभाव होता है। यहाँ प्राथमिक लाभ एक हैं toString कार्यान्वयन और एक hashCode मूल्य कि प्रक्रियाओं पर एक जैसी है। ध्यान दें कि केस ऑब्जेक्ट्स (सही ढंग से) संदर्भ समानता का उपयोग करते हैं:

object Foo extends Product with Serializable {
  def productArity: Int = 0

  def productIterator: Iterator[Any] =
    scala.runtime.ScalaRunTime.typedProductIterator(this)

  def productElement(i: Int): Any =
    throw new IndexOutOfBoundsException(i.toString)

  def productPrefix: String = "Foo"

  def canEqual(obj: Any): Boolean = obj.isInstanceOf[this.type]

  override def hashCode(): Int = 70822 // "Foo".hashCode()

  override def toString: String = "Foo"
}

मैन्युअल रूप से उन तरीकों को लागू करना अभी भी संभव है जो अन्यथा वर्ग और स्वयं के साथी ऑब्जेक्ट में case संशोधक द्वारा प्रदान किए जाएंगे।

केस क्लास बेसिक्स

नियमित कक्षाओं की तुलना में - केस क्लास संकेतन कई लाभ प्रदान करता है:

  • सभी कंस्ट्रक्टर तर्क public और प्रारंभिक ऑब्जेक्ट्स पर एक्सेस किए जा सकते हैं (आमतौर पर यह मामला नहीं है, जैसा कि यहां दिखाया गया है):

    case class Dog1(age: Int)
    val x = Dog1(18)
    println(x.age) // 18 (success!)
    
    class Dog2(age: Int)
    val x = new Dog2(18)
    println(x.age) // Error: "value age is not a member of Dog2"
    
  • यह निम्नलिखित विधियों के लिए एक कार्यान्वयन प्रदान करता है: toString , equals , hashCode (गुणों के आधार पर), copy , apply और unapply :

    case class Dog(age: Int)
    val d1 = Dog(10)
    val d2 = d1.copy(age = 15)
    
  • यह पैटर्न मिलान के लिए एक सुविधाजनक तंत्र प्रदान करता है:

    sealed trait Animal // `sealed` modifier allows inheritance within current build-unit only
    case class Dog(age: Int) extends Animal
    case class Cat(owner: String) extends Animal
    val x: Animal = Dog(18)
    x match {
        case Dog(x) => println(s"It's a $x years old dog.")
        case Cat(x) => println(s"This cat belongs to $x.")
    }
    

केस क्लासेस और इम्यूटेबिलिटी

स्केल संकलक पैरामीटर सूची में प्रत्येक तर्क को val साथ डिफ़ॉल्ट रूप से उपसर्ग करता है। इसका मतलब है कि, डिफ़ॉल्ट रूप से, केस कक्षाएं अपरिवर्तनीय हैं। प्रत्येक पैरामीटर को एक एक्सेसर विधि दी जाती है, लेकिन कोई उत्परिवर्ती विधियां नहीं होती हैं। उदाहरण के लिए:

case class Foo(i: Int)

val fooInstance = Foo(1)
val j = fooInstance.i       // get
fooInstance.i = 2           // compile-time exception (mutation: reassignment to val)

किसी मामले की श्रेणी में एक पैरामीटर की घोषणा करना क्योंकि var डिफ़ॉल्ट व्यवहार को ओवरराइड करता है और केस क्लास को परिवर्तनशील बनाता है:

case class Bar(var i: Int)

val barInstance = Bar(1)
val j = barInstance.i       // get
barInstance.i = 2           // set

एक अन्य उदाहरण जब एक केस क्लास 'म्यूटेबल' होता है, जब केस क्लास में वैल्यू म्यूटेबल होती है:

import scala.collection._

case class Bar(m: mutable.Map[Int, Int])

val barInstance = Bar(mutable.Map(1 -> 2))
barInstance.m.update(1, 3)                  // mutate m
barInstance                                 // Bar(Map(1 -> 3)

ध्यान दें कि यहाँ होने वाला in उत्परिवर्तन ’उस मानचित्र में होता है जो m इंगित करता है, केवल m को नहीं। इस प्रकार, यदि किसी सदस्य के रूप में किसी अन्य वस्तु में m होता है, तो यह परिवर्तन को भी देखेगा। ध्यान दें कि निम्नलिखित उदाहरण बदलते instanceA भी कैसे बदलता है instanceB :

import scala.collection.mutable

case class Bar(m: mutable.Map[Int, Int])

val m = mutable.Map(1 ->2)
val barInstanceA = Bar(m)
val barInstanceB = Bar(m)
barInstanceA.m.update(1,3)
barInstanceA  // Bar = Bar(Map(1 -> 3))
barInstanceB  // Bar = Bar(Map(1 -> 3))
m  // scala.collection.mutable.Map[Int,Int] = Map(1 -> 3)

कुछ परिवर्तन के साथ एक वस्तु की प्रतिलिपि बनाएँ

केस क्लासेस एक copy मेथड प्रदान करता है जो एक नया ऑब्जेक्ट बनाता है जो कुछ बदलावों के साथ पुराने फ़ील्ड के समान शेयर करता है।

हम इस सुविधा का उपयोग पिछले ऑब्जेक्ट से एक नई वस्तु बनाने के लिए कर सकते हैं जिसमें कुछ समान विशेषताएं हैं। इस सुविधा को प्रदर्शित करने के लिए यह सरल केस क्लास:

case class Person(firstName: String, lastName: String, grade: String, subject: String)
val putu = Person("Putu", "Kevin", "A1", "Math")
val mark = putu.copy(firstName = "Ketut", lastName = "Mark")
// mark: People = People(Ketut,Mark,A1,Math)

इस उदाहरण में हम देख सकते हैं कि दो वस्तुएं समान विशेषताओं ( grade = A1 , subject = Math ) को साझा करती हैं, सिवाय इसके कि उन्हें कॉपी ( firstName और lastName ) में निर्दिष्ट किया गया है।

टाइप सेफ्टी के लिए सिंगल एलिमेंट केस क्लासेस

प्रकार सुरक्षा प्राप्त करने के लिए कभी-कभी हम अपने डोमेन पर आदिम प्रकारों के उपयोग से बचना चाहते हैं। उदाहरण के लिए, किसी Person के name साथ कल्पना name । आमतौर पर, हम String रूप में name को एनकोड करेंगे। हालांकि, यह एक मिश्रण करने के लिए कठिन नहीं होगा String एक का प्रतिनिधित्व Person के name एक साथ String एक त्रुटि संदेश का प्रतिनिधित्व:

def logError(message: ErrorMessage): Unit = ???
case class Person(name: String)
val maybeName: Either[String, String] = ??? // Left is error, Right is name
maybeName.foreach(logError) // But that won't stop me from logging the name as an error!

इस तरह के नुकसान से बचने के लिए आप डेटा को इस तरह से एनकोड कर सकते हैं:

case class PersonName(value: String)
case class ErrorMessage(value: String)
case class Person(name: PersonName)

और अब हमारा कोड संकलित नहीं करेगा यदि हम PersonName को ErrorMessage , या यहां तक कि एक साधारण String साथ PersonName

val maybeName: Either[ErrorMessage, PersonName] = ???
maybeName.foreach(reportError) // ERROR: tried to pass PersonName; ErrorMessage expected
maybeName.swap.foreach(reportError) // OK

लेकिन यह एक छोटे से रन ओवरहेड को PersonName क्योंकि अब हमें अपने PersonName कंटेनर से बॉक्स / अनबॉक्स String एस / PersonName । आदेश में इस से बचने के लिए, एक बना सकते हैं PersonName और ErrorMessage मूल्य वर्गों:

case class PersonName(val value: String) extends AnyVal
case class ErrorMessage(val value: String) extends AnyVal


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow